两年前曾经学习过Hibernate,也通过博客将Hibernate的学习过程记录下来了,地址如下:
最近在复习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方法
实体类创建好了,需要创建相应的hbm文件:
<?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>
并将User.bhm.xml文件在Hibernate的配置文件中注册:
<mapping resource="com/hib/model/User.hbm.xml"/>
四、创建HibernateUtil.java类
创建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();
}
}
}
五、CRUD操作
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);
}
}
5.2 测试load方法
@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语句的。
而Hibernate的get方法无论是否使用user,都会发出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);
}
}
5.4 测试delete方法
@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);
}
}
5.5 测试List方法
@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);
}
}
5.6 测试分页
@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);
}
}
六、Hibernate的三种状态
临时状态(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,再添加Many:
//先添加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>