两年前曾经学习过Hibernate,也通过博客将Hibernate的学习过程记录下来了,地址如下:
Hibernate学习笔记(1)
Hibernate学习笔记(2)
最近在复习Hibernate,在重新学习的过程中,有了一些新的体会和收获,现在将其总结成博客,供以后作为参考资料使用。
一、导入相应的jar包
目前Hibernate更新到了4.x版本,在官网下载后,找到lib文件加中的required文件夹,此外还需要额外导入log4j和数据库驱动包。
二、创建Hibernate配置文件
在src目录下创建相应的hibernate.cfg.xml在这个文件中加入相应的数据库配置信息,而Hibernate.cfg.xml文件可以在Hibernate下载文件夹中找到模板。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="show_sql">true</property> <!-- hibernate基本配置 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置方言,用来确定连接的数据库 --> <!-- 数据库的连接 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">123456</property> <!-- 自动完成类到数据包的转化 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 加入实体类的映射文件 --> <mapping resource="com/hib/model/User.hbm.xml"/> </session-factory> </hibernate-configuration>
public class User { private int id; private String username; private String password; private String nickname; <span style="white-space:pre"> </span>//省略setter和getter方法
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hib.model"> <class name="User" table="t_user"> <id name="id"> <generator class="native" /> <!-- native自动递增 --> </id> <property name="username"/> <property name="password"/> <property name="nickname"/> <property name="born" type="timestamp"/> </class> </hibernate-mapping>
<mapping resource="com/hib/model/User.hbm.xml"/>
创建SessionFactory,它是线程安全的,所以整个SessionFactory应该基于单例的模式来创建。
public class HibernateUtil { private final static SessionFactory FACTORY = buildSessionFactory(); private static SessionFactory buildSessionFactory() { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(cfg.getProperties()).buildServiceRegistry(); SessionFactory factory = cfg.buildSessionFactory(serviceRegistry); return factory; } public static SessionFactory getSessionFactory() { return FACTORY; } public static Session openSession() { return FACTORY.openSession(); } public static void close(Session session) { if (session != null) { session.close(); } } }
5.1 测试插入数据
@Test public void testAdd() { Session session = null; Transaction transaction = null; try { session = HibernateUtil.openSession(); transaction = session.beginTransaction(); User u = new User(1, "悟净", "123456", "沙僧", new Date()); session.save(u); transaction.commit(); } catch (Exception e) { e.printStackTrace(); if(session != null){ transaction.rollback(); } }finally{ HibernateUtil.close(session); } }
@Test public void testLoad() { Session session = null; try { session = HibernateUtil.openSession(); User u = (User) session.load(User.class, 1); <span style="font-family: Arial, Helvetica, sans-serif;">//只有当使用user时,才发出sql语句,否则不发sql语句</span> User user = (User) session.get(User.class, 2); //无论是否使用user,都会发出sql语句 } catch (Exception e) { e.printStackTrace(); }finally{ HibernateUtil.close(session); } }延迟加载:当完成了load操作以后,并不会马上发出sql语句,只有在使用该对象时才会发出sql。当完成load之后,其实返回一个代理对象,这个代理对象中仅仅只有一个id的值,所以,如果仅仅是打印id,则是不会发出sql语句的。
5.3 测试update方法
@Test public void testUpdate() { Session session = null; Transaction transaction = null; try { session = HibernateUtil.openSession(); transaction = session.beginTransaction(); User u = (User) session.load(User.class, 1); u.setNickname("小四"); session.update(u); transaction.commit(); } catch (Exception e) { e.printStackTrace(); if(session != null){ transaction.rollback(); } }finally{ HibernateUtil.close(session); } }
@Test public void testDelete() { Session session = null; Transaction transaction = null; try { session = HibernateUtil.openSession(); transaction = session.beginTransaction(); User u = new User(); u.setId(1); session.delete(u); transaction.commit(); } catch (Exception e) { e.printStackTrace(); if(session != null){ transaction.rollback(); } }finally{ HibernateUtil.close(session); } }
@Test public void testList() { Session session = null; try { session = HibernateUtil.openSession(); List<User> users = session.createQuery("from User").list(); System.out.println(users); } catch (Exception e) { e.printStackTrace(); }finally{ HibernateUtil.close(session); } }
@Test public void testPager() { Session session = null; try { session = HibernateUtil.openSession(); List<User> users = session.createQuery("from User").setFirstResult(0).setMaxResults(2).list(); System.out.println(users); } catch (Exception e) { e.printStackTrace(); }finally{ HibernateUtil.close(session); } }
临时状态(Transient):用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫临时对象;
持久化状态(Persistent):已经持久化,加入到了Session缓存中。如通过hibernate语句保存的对象。处于此状态的对象叫持久对象;
游离状态(Detached):持久化对象脱离了Session的对象。如Session缓存被清空的对象。特点:已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;
已经有人对Hibernate的三种状态做了详细的描述,请参考:http://www.cnblogs.com/xiaoluo501395377/p/3380270.html
七、ManyToOne单向
所谓ManyToOne的关系,如Student和Classroom的关系,多个Student对应一个Classroom。一般是在many的一方添加外键:
public class Classroom { private int id; private String name; private int grade;
public class Student { private int id; private String name; private String no; private Classroom classroom;
//先添加one Classroom classroom = new Classroom(1, "计算机网络", 2015); session.save(classroom); //再添加many Student stu1 = new Student(1, "孙悟空", "001", classroom); session.save(stu1); Student stu2 = new Student(1, "猪八戒", "002", classroom); session.save(stu2);
<!-- many-to-one用来映射多对一,name表示对象中属性名称,column表示属性名称 --> <!-- 当设置了cascade时,会自动完成关联对象,会自动创建一个关联对象 --> <!-- 如果没有特殊情况,不要使用cascade,可能使用cascade的地方,一般都是one的一方进行删除时使用,特殊需求才会使用cascade,正常情况add方法都是由程序员完成添加 --> <many-to-one name="classroom" column="cid" cascade="all"></many-to-one>