Hibernate简介以及简单使用
Hibernate
1 Hibernate简介
Hibernate是一个开放源代码的对象关系映射框架(ORM),它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
ORM Object Relational Mapping
持久层框架: Mybatis Hibernate OJB JDO Toplink...
Hibernate版本: 2.x,3.x,4.x,5.x(目前最高版本 5.2.10)
2 hibernate使用
2.1 jar包导入
hibernate3.jar
lib/required/*.jar
lib/jpa/*.jar JPA Java Persistance API
数据库驱动包
2.2 hibernate配置文件
2.2.1 总体配置文件(hibernate.cfg.xml)
作用: 配置数据连接信息,加载映射配置文件等
|
<!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> <!-- 一个sessionFactory 就表示一个数据库连接 --> <!-- 数据库方言 --> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <!-- 数据库连接信息 --> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="connection.url"> jdbc:mysql:///db0729 </property> <property name="connection.username">root</property> <property name="connection.password">mysql</property> <!-- 数据库连接信息 --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- 加载映射配置文件 --> <mapping resource="com/zrgk/entity/User.hbm.xml" /> </session-factory> </hibernate-configuration> |
2.2.2 映射配置文件(***.hbm.xml)
作用:配置数据库表和实体类,表的字段和实体类属性的对应关系
|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.zrgk.entity.User" table="user"> <id name="id" column="id"> <generator class="native"></generator> </id> <property name="name" column="name" type="string"></property> <property name="age" type="java.lang.Integer"></property> <property name="birthday" type="java.util.Date"></property> </class> </hibernate-mapping> |
2.3 Hibernate入门程序
2.3.1 添加操作
|
//1 Configuration 加载hibernate总体配置文件 Configuration cfg = new Configuration().configure(); //2 创建SessionFactory SessionFactory sf = cfg.buildSessionFactory(); //3 创建Session Session session = sf.openSession(); //4 开启事务 Transaction Transaction tx = session.beginTransaction(); User user = new User(); user.setName("李四"); user.setAge(20); user.setBirthday(new Date()); //5保存数据 session.save(user);//返回值是新添加的数据的主键值 //6提交事务 tx.commit(); //7关闭session session.close(); |
2.3.2 根据主键(OID)查询
|
Load: Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(); Session session = sf.openSession();
//查询 有无事务都可
User user = (User)session.load(User.class, 10);
//System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getAge()+"\t"+user.getBirthday());
user.getName();
session.close();
System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getAge()+"\t"+user.getBirthday()); |
|
Get: Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(); Session session = sf.openSession(); User user = (User)session.get(User.class, 10); //System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getAge()+"\t"+user.getBirthday());
session.close(); System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getAge()+"\t"+user.getBirthday()); |
get方法和load方法的区别:
1 get方法查询时是立即加载(执行get方法后,立即向数据库发送sql语句查询回数据)
load方法查询时才用的是延时加载(执行load方法时,并没有向数据库发送sql语句查询数据,而是返回一个代理对象。load方法是在第一次获取代理对象中,非主键的属性时,才发送sql语句进行查询)
2 当根据所给主键,查不到数据时, get方法 返回 null
load方法 抛异常
2.3.3 封装获取Session的工具类
|
public class HibernateUtil { /* * SessionFactory是一个重量级对象(创建和销毁时都要消耗比较多的内存和资源) * * 1 加载映射配置文件 * 2 生成预定义的sql * 3 为创建Session准备环境 * * 把SessionFactory 设置成 静态的 * * */ private static SessionFactory factory; public static SessionFactory getSessionFactory(){ if(factory==null){ Configuration cfg = new Configuration().configure(); factory = cfg.buildSessionFactory(); } return factory; } public static Session getSession(){ return getSessionFactory().openSession(); } } |
2.4 实体对象在hibernate中的三种状态
1 瞬时(临时) Transient
刚new出来的对象
1、生命周期没有被session管理
2、不和数据库中的任何一条数据对应(这里所谓的对应就是指主键对应)
2 持久化 Persistent
1 对象的生命周期被session管理
2 和数据库中的一条数据对应
3 脱管(游离) Detached
1 对象的生命周期没有被session管理
2 和数据库中的一条数据对应
new
get() save() delete()
load() saveOrupdate()
iterate()
evict() update()
close() saveOrUpdate()
clear() lock() (过时)
2.5 更新操作
|
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.update(user); // 这里的user对象是持久化状态的对象(即,主键值和数据库中的一条数据对应)
tx.commit();
session.close(); |
2.6 删除操作
|
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.delete(user); // 这里的user对象是持久化状态的对象(即,主键值和数据库中的一条数据对应) tx.commit(); session.close(); |
2.7 saveOrUpdate方法
|
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.saveOrUpdate(user); // 返回值是所添加的数据的主键值 //如果主键值和数据库中的一条数据对应,则执行更新操作。没有对应,执行添加操作 tx.commit(); session.close(); |
2.8 关于快照
|
User user= new User(); user.setName(“张三”); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(user); // 持久化 user.setName("李四"); // 持久化 tx.commit(); session.close(); |
会生成insert 和 update语句。
session.save(user)
Persist
commit() 提交时,hibernate会拿持久化对象和照片做对比,如果有不同,则生成update语句
close()
2.9将图片(二进制文件)存入数据库
修改MySQL允许上传文件的大小,在my.ini文件中添加
|
max_allowed_packet=500M |
|
<class name="com.zrgk.domain.User" table="user">
<id name="id" column="id"> <generator class="native"/> </id>
<property name="name" column="name"></property> <property name="age"></property> <property name="birthday" ></property> <property name="photo" type="binary"></property> </class> |
|
User user = new User(); // 瞬时 user.setName("张三"); user.setAge(20); user.setBirthday(new Date()); InputStream is = new FileInputStream("D:/img-12.jpg"); byte[] b = new byte[is.available()]; is.read(b); user.setPhoto(b); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(user); // 持久化 tx.commit(); session.close(); |
3 主键生成策略
3.1 increment
整数类型的主键,采用取最大值+1的策略
集群环境不适合使用
3.2 identity
整数类型的主键, 支持自增的数据库 ---- 把主键的维护交给数据库,hibernate不维护主键
3.3 sequence
整数类型的主键,支持序列的数据库
|
<id name="id"> <generator class="sequence"></generator> </id> |
默认使用的是 hibernate_sequence 这个序列
如何指定其他序列???
|
<id name="id"> <generator class="sequence"> <param name="sequence">user_seq</param> </generator> </id> |
3.4 UUID
字符串类型的主键
3.5 guid
SQLServer、MySQL支持,字符串类型的主键
3.6 native
根据数据库选择 identity hilo sequence
3.7assigned
手动分配主键
3.8 联合主键
composite-id 包含联合主键的类,必须实现 Serializable接口
方式1:
|
class Person{ private String firstName; private String lastName; private int age; } |
|
<composite-id> <key-property name="firstName" column="first_name"></key-property> <key-property name="lastName" column="last_name"></key-property> </composite-id> |
方式2
|
class Name{ private String firstName; private String lastName; }
class Teacher{ private Name name; private int age; } |
|
<composite-id name="name"> <key-property name="firstName" column="first_name"></key-property> <key-property name="lastName" column="last_name"></key-property> </composite-id> |
3.9自定义主键生成策略
|
public class MyGenerator implements IdentifierGenerator,Configurable { private String formatStr="yyyyMMddhhmmss"; @Override public Serializable generate(SessionImplementor arg0, Object arg1) throws HibernateException { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(formatStr); //Connection conn = arg0.connection(); String str = sdf.format(date); return str; } @Override public void configure(Type arg0, Properties arg1, Dialect arg2) throws MappingException { formatStr = (String)arg1.get("formatStr");
} } |
|
<hibernate-mapping package="com.zrgk.domain"> <class name="Student"> <id name="num"> <!-- <generator class="uuid"/> --> <generator class="com.zrgk.util.MyGenerator"> <param name="formatStr">yyyy-MM-dd-hh-mm-ss</param> </generator> </id> <property name="name"></property> <property name="age"></property> </class> </hibernate-mapping> |
4 hibernate一级缓存
Session级别的缓存,自动开启,不能关闭。
|
Session session = HibernateUtil.getSession(); User user = (User)session.get(User.class, 1); User user2 = (User)session.get(User.class,1); // 从缓存中取 session.close(); System.out.println(user.getId()+"\t"+user.getName()+"\t"+user.getAge()); System.out.println(user2.getId()+"\t"+user2.getName()+"\t"+user2.getAge());
Session session2 = HibernateUtil.getSession(); User user3 = (User)session2.get(User.class, 1); session2.close(); System.out.println(user3.getId()+"\t"+user3.getName()+"\t"+user3.getAge()); |
清除缓存:
session.flush() 清session的缓存,把数据同步到数据库中。
session.clear() 清session的缓存,数据不会同步到数据库中。
session.evict(user) 把指定对象从session的缓存中清除,数据不会同步到数据库中。
因为在添加数据(调用save方法)时,对象会被存入一级缓存中,因此,当大批量添加数据时,需要定时清除缓存
|
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); long begin = System.currentTimeMillis(); for(int i=1;i<=100000;i++){ User user = new User(); user.setName("test"+i); user.setAge(20); session.save(user); if(i%50==0){ session.flush(); } } tx.commit(); session.close(); long end = System.currentTimeMillis(); System.out.println("共用了"+(end-begin)/1000+"秒"); |
5 关联关系映射
5.2 多对一
配置方式:
|
<many-to-one name="多方存一方时对象名" class="一方的类名" column="外键列名"> </many-to-one> |
|
<many-to-one name="department" class="Department" column="dept_id" cascade="delete"> </many-to-one> |
属性说明:
cascade(级联操作):
none (默认) 不级联
save-update 级联保存和更新
delete 级联删除
all 包括 save-update 和 delete
delete-orphan 删除孤儿
all-delete-orphan
lazy(延时加载):
proxy 默认 延时加载
no-proxy 延时加载
false 立即加载
|
@Test public void test1(){ // 只保存employee Employee e1 = new Employee(); e1.setName("小毛"); e1.setSalary(1000); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(e1); // 保存成功 tx.commit(); session.close(); } @Test public void test2(){ Employee e1 = new Employee(); e1.setName("小邓"); e1.setSalary(1000); Department d = new Department(); d.setName("研发部"); // 这时表中还没有这个部门 e1.setDepartment(d); // 建立员工和部门的关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(e1); // 保存失败,外键无法赋值 tx.commit(); session.close(); } @Test public void test3(){ Employee e1 = new Employee(); e1.setName("小邓"); e1.setSalary(1000); Department d = new Department(); d.setId(1); // 脱管对象, --研发部 e1.setDepartment(d); // 建立员工和部门的关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(e1); // 添加成功!!! (当部门已经存在时,保存成功) tx.commit(); session.close(); } @Test public void test4(){ // 级联保存 cascade="save-update" Employee e1 = new Employee(); e1.setName("小江"); e1.setSalary(1000); Department d = new Department(); d.setName("测试部"); e1.setDepartment(d); // 建立员工和部门的关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(e1); //级联保存,先存部门,再存员工 tx.commit(); session.close(); } @Test public void test5(){ // 删除 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Employee e = (Employee)session.get(Employee.class,4); session.delete(e); tx.commit(); // 只删多方,可以删除 session.close();
} @Test public void test6(){ // 级联删除 cascade="delete" “一般不用!!!!” Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Employee e = (Employee)session.get(Employee.class,1); session.delete(e); //级联删除,也会删除对应的部门,如何这个部门被其他员工,会把其他员工的外键更新为null tx.commit(); session.close();
} @Test public void test7(){ //解除关系 解除小江和研发部的关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Employee e = (Employee)session.get(Employee.class,3); e.setDepartment(null); // 解除关系 // session.update(e); //这句可以省略 tx.commit(); session.close(); } @Test public void test8(){ //把小江从研发部调到测试部 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Employee e = (Employee)session.get(Employee.class,3); Department d = (Department)session.get(Department.class, 2); e.setDepartment(d); // 调职 session.update(e); tx.commit(); session.close(); } @Test public void test9(){ // 查询 Session session = HibernateUtil.getSession();
Employee e = (Employee)session.get(Employee.class,3); System.out.println(e.getId()+"\t"+e.getName()+"\t"+e.getSalary()+"\t"+e.getDepartment().getName()); // 多对一时,关联对象会被直接查询出来 (只查employee时,对应的department会被查询 session.close();
} @Test public void test10(){ // 查询 Session session = HibernateUtil.getSession(); Employee e = (Employee)session.get(Employee.class,3); //e.getDepartment().getName(); session.close();
System.out.println(e.getId()+"\t"+e.getName()+"\t"+e.getSalary()); System.out.println(e.getDepartment().getName()); // 关联对象默认是延时加载的(懒加载) } |
5.2 一对多
|
<set name="employeeSet" cascade="save-update,delete"> <key column="dept_id"></key> <one-to-many class="Employee" /> </set> |
属性说明:
cascade
save-update delete delete-orphan
lazy
true 默认,延时加载
false 立即加载
extra 延时加载 (比lazy="true"还懒)
inverse
true
多数一对多(多对一)操作,都会把inverse 设置为true , 让一方放弃对外键的维护
|
@Test public void test1(){ //添加 --- 只添加一方 Department d = new Department(); d.setName("市场部"); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(d); tx.commit(); session.close(); } @Test public void test2(){ //添加 Department d = new Department(); d.setName("人事部"); Employee e1 = new Employee(); e1.setName("老大"); e1.setSalary(1000); Employee e2 = new Employee(); e2.setName("老二"); e2.setSalary(1000); e1.setDepartment(d); // 建立关系 e2.setDepartment(d); // 建立关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(d); // 只会保存 d 和e1 e2 没有任何关系 tx.commit(); session.close(); } @Test public void test3(){ //级联保存 cascade="save-update"
Department d = new Department(); d.setName("人事部"); Employee e1 = new Employee(); e1.setName("老大"); e1.setSalary(1000); Employee e2 = new Employee(); e2.setName("老二"); e2.setSalary(1000); e1.setDepartment(d); // 建立关系 e2.setDepartment(d); // 建立关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(d); //没有级联的效果!!! 原因是,建立关系是在多方建立的 tx.commit(); session.close(); }
@Test public void test4(){ //级联保存 cascade="save-update" Department d = new Department(); d.setName("人事部"); Employee e1 = new Employee(); e1.setName("老大"); e1.setSalary(1000); Employee e2 = new Employee(); e2.setName("老二"); e2.setSalary(1000); d.getEmployeeSet().add(e1); d.getEmployeeSet().add(e2); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(d); //可以级联保存 tx.commit(); session.close(); } @Test public void test6(){ //删除 没有被多方参照的一方 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,3); session.delete(d); // 可以删除 tx.commit(); session.close(); } @Test public void test7(){ //删除 有被多方参照的一方 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,6); session.delete(d); // 可以删除, 也可以被删除,多方的外键被更新为null tx.commit(); session.close(); } @Test public void test8(){ //级联删除 cascade="delete" Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,2); session.delete(d); // tx.commit(); session.close(); } @Test public void test9(){ // 解除关系 解除研发部和小邓的关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,1); // 研发部 Employee e = (Employee)session.get(Employee.class,2); // 小邓 d.getEmployeeSet().remove(e); // 解除关系 session.update(d); tx.commit(); session.close(); } @Test public void test10(){ // 解除关系 解除研发部下的所有关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,1); // 研发部 d.setEmployeeSet(null); session.update(d); tx.commit(); session.close(); } @Test public void test11(){ // 删除孤儿 cascade="delete-orphan" Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,1); // 研发部 Employee e = (Employee)session.get(Employee.class,2); // 小邓 d.getEmployeeSet().remove(e); // 解除了研发部和小邓的关系, 小邓就变成了孤儿 // 由于是删除孤儿,所以 小邓会被删除 // 这里的删除孤儿,之后删除由于解除关系操作变成的孤儿,原有的孤儿是不会被删除的 session.update(d); tx.commit(); session.close(); } @Test public void test12(){ // 只查一方 Session session = HibernateUtil.getSession(); Department d = (Department)session.get(Department.class,1); // 研发部 System.out.println(d.getName()); session.close(); } @Test public void test13(){ // 查询 Session session = HibernateUtil.getSession(); Department d = (Department)session.get(Department.class,1); // 研发部 System.out.println(d.getName()); for(Employee e:d.getEmployeeSet()){ System.out.println(e.getName()); } session.close(); } @Test public void test14(){ // 查询 ----- 关联对象延时加载 Session session = HibernateUtil.getSession(); Department d = (Department)session.get(Department.class,1); // 研发部 System.out.println(d.getName()); session.close(); for(Employee e:d.getEmployeeSet()){ System.out.println(e.getName()); } } @Test public void test15(){ // 查询 ----- 关联对象延时加载
Session session = HibernateUtil.getSession();
Department d = (Department)session.get(Department.class,1); // 研发部
System.out.println(d.getName()); d.getEmployeeSet().size(); // 在session关闭之前取 --- lazy="extra" 当取集合的size时,只会生成 count语句 session.close(); for(Employee e:d.getEmployeeSet()){ System.out.println(e.getName()); } } @Test public void test16(){ // inverse="true" 把小毛调到测试部 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Department d = (Department)session.get(Department.class,2); // 测试部 Employee e = (Employee)session.get(Employee.class,1); e.setDepartment(d); d.getEmployeeSet().add(e); // 其实这句话是一个多余的操作~~~ 但这句话引起了一个update语句 // 能够反映出,一方,多方都会去维护外键列 // 一般情况下,不站在一方操作外键。 inverse="true" 是指,一方放弃对外键的维护 session.update(e); tx.commit(); session.close(); } @Test public void test17(){ // inverse="true" 级联保存 cascade="save-update" Department d = new Department(); d.setName("人事部"); Employee e1 = new Employee(); e1.setName("老大"); e1.setSalary(1000); Employee e2 = new Employee(); e2.setName("老二"); e2.setSalary(1000); d.getEmployeeSet().add(e1); d.getEmployeeSet().add(e2); e1.setDepartment(d); e2.setDepartment(d);
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); session.save(d); // 虽然级联保存成功,但多方外键没有值,因为一方放弃了对外键的维护 tx.commit(); session.close(); }
|
5.2 多对多
|
<set name="本方存对方集合的名称" table="中间表表名"> <key column="中间表中参照本方的外键列名"></key> <many-to-many class="集合中数据的类型" column="中间表中参照对方的外键列名"></many-to-many> </set> |
|
<set name="courseSet" table="student_course" cascade="save-update,delete" lazy="false"> <key column="student_id"></key> <many-to-many class="Course" column="course_id"></many-to-many> </set> |
属性说明:
cascade
lazy
inverse 多对多时,比较少站在哪一端操作,就把哪一端的inverse设置为true
|
@Test public void test1(){ // 添加 Student Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s = new Student(); s.setName("张三"); session.save(s); tx.commit(); session.close(); }
@Test public void test2(){ // 添加 Course Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Course c = new Course(); c.setName("数学"); session.save(c); tx.commit(); session.close(); } @Test public void test3(){ // 级联保存 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s = new Student(); s.setName("李四"); Course c1 = new Course(); c1.setName("语文"); Course c2 = new Course(); c2.setName("英语"); s.getCourseSet().add(c1); s.getCourseSet().add(c2); session.save(s); tx.commit(); session.close(); } @Test public void test4(){ // 删除 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s =(Student)session.get(Student.class,2); session.delete(s); // 可以删除,外键会被更新为null tx.commit(); session.close(); } @Test public void test5(){ // 级联删除 cascade="delete" Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s =(Student)session.get(Student.class,2); session.delete(s); // 课程被其他学生参照时,不能实现级联删除 tx.commit();
session.close(); } @Test public void test6(){ // 修改张三所选课程 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s =(Student)session.get(Student.class,1); Course c1 = (Course)session.get(Course.class,1); Course c2 = (Course)session.get(Course.class,2); s.setCourseSet(null); /*s.getCourseSet().add(c1); s.getCourseSet().add(c2);*/ Set<Course> set = new HashSet<Course>(); set.add(c1); set.add(c2); s.setCourseSet(set); session.update(s); tx.commit(); session.close();
} @Test public void test7(){ // 查询 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Student s =(Student)session.get(Student.class,1); System.out.println(s.getName()); for(Course c:s.getCourseSet()){ System.out.println(c.getName()); } tx.commit(); session.close();
} @Test public void test8(){ // 查询 ---- 关联关系,延时加载 Session session = HibernateUtil.getSession(); Student s =(Student)session.get(Student.class,1); System.out.println(s.getName()); session.close(); for(Course c:s.getCourseSet()){ System.out.println(c.getName()); } } @Test public void test9(){ // 查询 ---- 关联关系,延时加载 lazy="false" Session session = HibernateUtil.getSession(); Student s =(Student)session.get(Student.class,1); System.out.println(s.getName()); session.close(); for(Course c:s.getCourseSet()){ System.out.println(c.getName()); } } |
5.2 一对一
5.2.1 主键关联
|
主控方: <!-- id被wife参照 主控方--> <class name="Husband"> <id name="id"> <generator class="native"></generator> </id> <property name="name"></property> <one-to-one name="wife" class="Wife" lazy="proxy"></one-to-one> </class> |
|
被控方: <!-- id参照husband 被控方--> <class name="Wife"> <id name="id"> <generator class="foreign"> <param name="property">husband</param> </generator> </id> <property name="name"></property> <one-to-one name="husband" class="Husband" constrained="true" cascade="delete"></one-to-one> </class> |
|
@Test public void test1(){ // 添加 Wife Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = new Wife(); w.setName("小红"); session.save(w); // 先添加wife 不可以的 tx.commit(); session.close(); }
@Test public void test2(){ // 添加 Husband Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = new Husband(); h.setName("小明"); session.save(h); tx.commit(); session.close(); } @Test public void test3(){ // 添加 Wife Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = new Wife(); w.setName("小红"); Husband h = (Husband)session.get(Husband.class,1); w.setHusband(h); session.save(w); tx.commit(); session.close(); } @Test public void test4(){ // 添加 Wife Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = new Wife(); w.setName("小栏"); Husband h = new Husband(); h.setName("小强"); w.setHusband(h); session.save(w); // 不需要配置,就会级联保存 tx.commit(); session.close(); } @Test public void test5(){ // 添加 Husband Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = new Wife(); w.setName("小花"); Husband h = new Husband(); h.setName("小刚"); h.setWife(w); session.save(h); // 不会有级联的效果 (保存主控方时) tx.commit(); session.close(); } @Test public void test6(){ // 添加 Husband cascade="save-update" Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = new Wife(); w.setName("X"); Husband h = new Husband(); h.setName("Y"); h.setWife(w); session.save(h); // 连husband都不能保存 tx.commit(); session.close(); } @Test public void test7(){ // 删除 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = (Husband)session.get(Husband.class,3); session.delete(h); // 没有被参照的,可以删除 tx.commit(); session.close(); }
@Test public void test8(){ // 删除
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = (Husband)session.get(Husband.class,1); session.delete(h); // 有被参照的,不能删除 tx.commit(); session.close(); } @Test public void test9(){ // 级联删除 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = (Husband)session.get(Husband.class,1); session.delete(h); // 可以 tx.commit(); session.close(); } @Test public void test10(){ // 删除被控方
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = (Wife)session.get(Wife.class,2); session.delete(w); // 可以 tx.commit(); session.close();
} @Test public void test11(){ // 级联删除被控方 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = (Wife)session.get(Wife.class,2); session.delete(w); // 可以 tx.commit(); session.close(); } @Test public void test12(){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = (Husband)session.get(Husband.class,1); Wife w = (Wife)session.get(Wife.class,1); h.setWife(null); session.update(h); tx.commit(); session.close(); }
@Test public void test13(){ // 关联关系 默认使用左外连接方式查询, 延时加载失效 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Husband h = (Husband)session.get(Husband.class,1); tx.commit(); session.close(); System.out.println(h.getName()); System.out.println(h.getWife().getName()); } @Test public void test14(){ // 查被控方,关联关系 默认延时加载 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Wife w = (Wife)session.get(Wife.class,1); tx.commit(); session.close(); System.out.println(w.getName()); System.out.println(w.getHusband().getName());
} |
5.2.2 唯一外键关联
|
<class name="Person"> <id name="id"> <generator class="identity"/> </id> <property name="name"></property> <one-to-one name="idcard" class="IdCard" property-ref="person" cascade="save-update,delete"></one-to-one> <!-- property-ref 对方存本方时,属性名 --> </class> |
|
<class name="IdCard"> <id name="id"> <generator class="identity"/> </id> <property name="num"></property> <many-to-one name="person" class="Person" unique="true" column="person_id" cascade="save-update,delete"></many-to-one> </class> |
|
@Test public void test1(){ // 添加Person Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = new Person(); p.setName("xxx"); session.save(p); tx.commit(); session.close(); } @Test public void test2(){ // 添加idcard Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); IdCard ic = new IdCard(); ic.setNum("88888888888888"); session.save(ic); tx.commit(); session.close(); } @Test public void test3(){ // 添加 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = new Person(); p.setName("yyy"); IdCard ic = new IdCard(); ic.setNum("99999999999999999999"); p.setIdcard(ic); session.save(p); // 不会级联 tx.commit(); session.close(); }
@Test public void test4(){ // 级联添加 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = new Person(); p.setName(""); IdCard ic = new IdCard(); ic.setNum("6666666666666"); p.setIdcard(ic); session.save(p); // OK tx.commit(); session.close(); } @Test public void test5(){ Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = new Person(); p.setName("ttt"); IdCard ic = new IdCard(); ic.setNum("777777777777"); //ic.setPerson(p); //建立关系后,双方都不能保存 session.save(ic); tx.commit(); session.close(); } @Test public void test6(){ // 级联 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = new Person(); p.setName("ttt"); IdCard ic = new IdCard(); ic.setNum("777777777777"); ic.setPerson(p); session.save(ic); // OK tx.commit(); session.close(); } @Test public void test7(){ // 删除Person Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = (Person)session.get(Person.class,1); session.delete(p); // 没有被参照的,可以删除 tx.commit(); session.close(); } @Test public void test8(){ // 删除Person Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = (Person)session.get(Person.class,4); session.delete(p); // 被参照的,不能删除 tx.commit(); session.close(); } @Test public void test9(){ // 级联删除 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = (Person)session.get(Person.class,4); session.delete(p); // 可以 tx.commit(); session.close(); } @Test public void test10(){ // 删除IdCard Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); IdCard ic = (IdCard)session.get(IdCard.class,1); session.delete(ic); // 可以 tx.commit(); session.close(); } @Test public void test11(){ // 级联删除idcard Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); IdCard ic = (IdCard)session.get(IdCard.class,5); session.delete(ic); // 可以 tx.commit(); session.close(); } @Test public void test12(){ // 解除关系 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); IdCard ic = (IdCard)session.get(IdCard.class,2); ic.setPerson(null); session.update(ic); tx.commit(); session.close(); } @Test public void test13(){ // 关联关系----- 立即加载,lazy失效 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Person p = (Person)session.get(Person.class,3); tx.commit(); session.close(); System.out.println(p.getName()); System.out.println(p.getIdcard().getNum()); } @Test public void test14(){ // 查被控方,延时加载 Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); IdCard ic = (IdCard)session.get(IdCard.class,2); tx.commit(); session.close(); System.out.println(ic.getNum()); System.out.println(ic.getPerson().getName()); } |
6 封装Hibernate的DAO模板类
|
接口: public interface BaseDao<T,PK extends Serializable> {
public void insert(T t); public void update(T t); public void delete(T t); public T findById(PK id); } |
|
实现类: public class BaseDaoImpl<T,PK extends Serializable> implements BaseDao<T, PK> { Class entityClass; public Class getEntityClass() { return entityClass; } public void setEntityClass(Class entityClass) { this.entityClass = entityClass; }
@Override public void insert(T t) { Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); session.save(t); tx.commit(); session.close(); }
@Override public void update(T t) { Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); session.update(t); tx.commit(); session.close(); } @Override public void delete(T t) { Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); session.delete(t); tx.commit(); session.close(); } @Override public T findById(PK id) { Session session = HibernateSessionFactory.getSession(); T t = (T)session.get(entityClass, id); session.close(); return t; } } |
使用:
|
public class UserDaoImpl extends BaseDaoImpl<User,Integer> implements UserDao { public UserDaoImpl(){ this.entityClass=User.class; } …… } |
7 hibernate中的查询
7.1根据id(OID)的查询(get或load方法)
7.2 Hql(Hibernate Query Language)
和sql语句的区别:关系型数据库的表名换成类名,列名换成成员变量的名字。
|
Query q=session.createQuery(“from Customer c where c.name=:name and c.age=:age”); q.setString(“name”,”aaa”);// q.setParameter("name","aaa"); q.setInteger(“age”,23); List result = q.list(); |
(参数绑定的两种方式,也可以使用问号) 索引从零开始
可以写成一条语句:
|
List result = session.createQuery(“from Customer c where c.name=:name and c.age=:age”).setString(“name”,”aaa”).setInteger(“age”,23).list(); |
当能确定是只返回一条时:
|
User user = session.createQuery(hql).setParameter("userName","zhangsan").uniqueResult(); |
当使用hql语句查询数据 做了投影时,将不会返回对象,将返回Object数组
可以这样来解决这个问题:
|
String hql = "select new domain.User(u.name,u.age) from User u where u.name like :uName"; |
User类中要有对应的构造方法(建议,查询时不做投影)
查询结果排序:
|
Query q=session.createQuery(“from User u order by u.name desc”); |
关于分页查询:
|
q.setFirstResult(0); //从哪条开始 q.setMaxResults(10); // 取几条 |
使用setParameter方法绑定任意类型的参数:
|
Query q=session.createQuery("from Order o where o.customer=:customer"+"and o.orderNumber like :orderNumber"); q.setParameter("customer",customer,Hibernate.entity(Customer.class)); q.setParameter("orderNumber",orderNumber,Hibernate.STRING); |
使用setProperties方法绑定参数:
|
Customer c=new Customer(); c.setName(“zhangsan”); c.setAge(33); Query q=session.createQuery(“from Customer c where c.name=:name and c.age=:age”); q.setProperties(c); |
在配置文件中编写hql语句:
|
<hibernate-mapping> <class name=“mypack.Customer” table=“CUSTOMERS”> </class> <query name=“aFind”><![CDATA[ from Customer c where c.name like :name]]></query> </hibernate-mapping>
Query q=session.getNamedQuery(“aFind”); q.setString(“name”,name); List result=q.list();
|
使用 group by 等
|
String hql = "select distinct u.id from User u join u.orders o group by u.id having sum(o.price)>:price"; Query q = s.createQuery(hql); q.setParameter("price", price); List list = q.list(); String hql2 = "select * from User u where u.id in (:userIds)"; Query q2 = s.createQuery(hql2); q2.setParameter("userIds", list); String hql = "from User u where u.orders is not empty"; |
7.3 QBC(Query By Criteria)
|
Criteria c=session.createCriteria(Customer.class); SimpleExpression c1=Restrictions.like(“name”,”zhang%”); SimpleExpression c2=Restrictions.eq(“age”,new Integer(99)); c=c.add(c1).add(c2); List result=c.list(); |
查询结果排序:
|
Criteria c=session.createCriteria(Customer.class); c.addOrder(Order.asc(“name”)); c.addOrder(Order.desc(“age”)); |
关于分页查询:
|
c.setFirstResult(0); c.setMaxResults(10); |
Criteria中的查询结果比较
|
检索年龄大于18的Customer: Criteria c=session.createCriteria(Customer.class); c.add(Restrictions.gt(“age”,18)); 检索年龄不等于18的Customer: c.add(Restrictions.not(Restrictions.eq(“age”,new Integer(18)))); not (age=18) 检索姓名为空的Customer: c.add(Restrictions.isNull(“name”));
检索不属于任何客户的订单: c.add(Restrictions.isNull(“customer”));
检索名字为zhangsan的客户: c.add(Restrictions.eq(“name”,”zhangsan”).ignoreCase()); ge---------------------->= le----------------------<= |
Criteria中的OR
|
Restrictions.or(Restrictions.eq(),Restrictions.or(Restrictions.between(),Resctions.like())) String[] names={“Tom”,”Mike”,”Jack”}; c.add(Restrictions.in(“name”,names)); |
between and
|
检索年龄不在18到30的客户: c.add(Restrictions.between(“age”,new Integer(18),new Integer(30)); |
not
|
检索年龄不在18到30的客户: c.add(Restrictions.not(Restrictions.between(“age”,new Integer(18),new Integer(30))); |
count和分组
|
Critieria c = s.createCriteria(Customer.class) c.setProjection(Projections.rowCount()); c.setProjection(Projections.groupProperty("sex"));
//Select count(*) from customer group by sex Critieria c = s.createCriteria(Customer.class).setProjection(Projections.ProjectionList().add(Projections.rowCount()).add(Projections.groupProperty("sex"))) c.setProjection(Projections.rowCount()); c.setProjection(Projections.groupProperty("sex"));
|
7.4 QBE(Query By Example)
|
Customer c=new Customer(); c.setAge(99); c.setName("aaa"); List result=session.createCriteria(Customer.class).add(Example.create(c)).list(); |
QBE只支持=和like,不支持or > <之类的查询
7.5 使用SQL
|
String sql = "select * from users u where u.name like :name"; Query q = s.createSQLQuery(sql).addEntity(User.class); q.setParameter("name", name); |
8 二级缓存
SessionFactory级别的缓存,需要手动开启。一般使用第三方提供的缓存。
8.1 开启二级缓存
|
hibernate.cfg.xml中开启: <!-- 开启二级缓存 --> <property name="cache.use_second_level_cache">true</property> <!-- 指定缓存提供商 EHCache --> <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 指定哪个类的对象会被方到二级缓存中 ,也可以在映射文件中指定--> <class-cache usage="read-only" class="com.zrgk.domain.User"/> |
|
<class name="User"> <!-- 指定这个类的对象会被方到二级缓存中 --> <cache usage="read-only" region="" /> |
8.2 ehcache文件
用来指定缓存规则
|
<ehcache> <diskStore path="java.io.tmpdir"/><!-- 缓存对象存在磁盘上路径 --> <!-- 缓存规则 maxElementsInMemory 内存中最多缓存多少个对象 timeToIdleSeconds 最大空闲时间(秒) timeToLiveSeconds 最大存活时间 overflowToDisk 内存中数量超过规定时,是否把对象存到磁盘上 eternal 是否是永久的
--> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> </ehcache> |
8.3 使用二级缓存
|
public static void main(String[] args) { //System.out.println(System.getProperty("java.io.tmpdir")); Session session = HibernateSessionFactory.getSession(); User user = (User)session.get(User.class, 1); session.close(); System.out.println(user.getId()+"\t"+user.getName()); //HibernateSessionFactory.getSessionFactory().evict(User.class); //清除二级缓存 Session session2 = HibernateSessionFactory.getSession(); User user2 = (User)session2.get(User.class, 1); session2.close(); System.out.println(user2.getId()+"\t"+user2.getName()); } |
9 getCurrentSession()的使用
要使用getCurrentSession() 方法,要在hibernate.cfg.xml中开启
<!-- 配置可以使用getCurrentSession -->
<property name="current_session_context_class">thread</property>
使用getCurrentSession() 获得的session 即使是查询,也要有事务!!!
这个session不需要手动close()
10 抓取策略 (fetch)
关联对象的查询,是跟抓取策略有关的。
<many-to-one fetch="" >
select (默认) -------- 关联对象延时加载,查关联对象时另外再发sql进行查询
join --------- 使用左外连接方式查询, lazy失效
<set fetch=""></set>
select(默认) ----- 关联对象延时加载,查关联对象时,另发sql
join ----- 使用左外连接方式查询, lazy失效
subselect ----- 关联对象延时加载,查关联对象时,另发sql
----- 查关联对象,会使用子查询的方式
select和subselect的区别:
|
Session session = HibernateSessionFactory.getSession(); Query query = session.createQuery("from Department where id in(1,2)"); List<Department> list = query.list(); for(Department d:list){ System.out.println(d.getName()); for(Employee e:d.getEmployeeSet()){ System.out.println(" "+e.getName()); } } session.close(); |
11 悲观锁和乐观锁
避免丢失更新问题
1 悲观锁 get(LockMode.UPGRADE)
2 乐观锁 依靠版本控制
11.1 悲观锁
|
public void test1(){ Session session = HibernateSessionFactory.getSession(); User user = (User)session.get(User.class,1,LockMode.UPGRADE); session.close(); }
//select * from user where id=1 for update @Test public void test2(){ Session session = HibernateSessionFactory.getSession(); User user = (User)session.get(User.class,1,LockMode.UPGRADE); session.close();
} |
11.2 乐观锁
|
public class User { private int id; private String name; private int age; private Date birthday; private String email; private int version; public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } |
|
<hibernate-mapping package="com.zrgk.domain"> <class name="User"> <id name="id"> <generator class="native"></generator> </id> <version name="version"></version> <property name="name"></property> <property name="age"></property> <property name="birthday"></property> <property name="email"></property> </class> </hibernate-mapping> |
|
@Test public void test1(){ Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); User user = (User)session.get(User.class,1); user.setName("xxx"); tx.commit(); session.close(); } @Test public void test2(){ Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); User user = (User)session.get(User.class,1); user.setName("yyy"); tx.commit(); session.close(); } |
12查询缓存
一级缓存和二级缓存只能缓存对象,查询缓存可以缓存普通属性。
12.1 开启查询缓存
|
<!-- 开启查询缓存--> <property name="hibernate.cache.use_query_cache">true</property> |
12.2 使用查询缓存
|
Session session = HibernateSessionFactory.getSession(); String hql = "select name from User where id=1"; // 指查name属性 Query q = session.createQuery(hql); q.setCacheable(true); // 开启查询缓存 String name1 = (String)q.uniqueResult(); q.setCacheable(true); // 每次查询都要调用这个方法开启查询缓存 String name2 = (String)q.uniqueResult(); System.out.println(name1+"\t"+name2); session.close(); Session session3 = HibernateSessionFactory.getSession(); String hql3 = "select name from User where id=1"; Query q3 = session3.createQuery(hql3); q3.setCacheable(true); // 开启查询缓存 String name3 = (String)q3.uniqueResult(); System.out.println(name3); session3.close(); |
13 spring整合hibernate
13.1 添加spring整合hibernate的jar包
org.springframework.orm-3.0.7.RELEASE.jar
13.2把hibernate的配置信息转移到spring配置文件中
|
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:dbconfig.properties</value> </list> </property> </bean> |
|
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${driver_class}"> </property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </bean> |
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource"></ref> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </prop>
<prop key="hibernate.show_sql">true</prop> </props> </property> <!-- <property name="mappingResources"> <list> <value>com/zrgk/domain/Department.hbm.xml</value> <value>com/zrgk/domain/User.hbm.xml</value> <value>com/zrgk/domain/Employee.hbm.xml</value> </list> </property> -->
<property name="mappingDirectoryLocations"> <list> <value>com/zrgk/domain</value> </list> </property> </bean> |
13.3使用模板类HibernateTemplate
|
<!-- 配置模板类 HibernateTemplate 要把sessionFactory注入给ht--> <bean id="ht" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
<!-- 配置BaseDao --> <bean id="baseDao" class="com.zrgk.dao.BaseDaoImpl" abstract="true"> <property name="ht" ref="ht"></property> </bean> <bean id="userDao" class="com.zrgk.dao.UserDaoImpl" parent="baseDao"></bean>
<bean id="userService" class="com.zrgk.service.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> |
|
public class BaseDaoImpl<T,PK extends Serializable> implements BaseDao<T, PK> { Class entityClass; private HibernateTemplate ht; // spring 的类 public HibernateTemplate getHt() { return ht; } public void setHt(HibernateTemplate ht) { this.ht = ht; } public Class getEntityClass() { return entityClass; } public void setEntityClass(Class entityClass) { this.entityClass = entityClass; } @Override public void insert(T t) { ht.save(t);
} @Override public void update(T t) { ht.update(t); } @Override public void delete(T t) { ht.delete(t); } @Override public T findById(PK id) { T t = (T)ht.get(entityClass, id); return t; } } |
13.4事务管理
|
<!-- 配置事务管理器 切面 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
<!-- 事务的传播规则 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="modify*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED"/> <tx:method name="zhuanzhang" propagation="REQUIRED" rollback-for="java.lang.NullPointerException"/> <tx:method name="*" propagation="REQUIRED" read-only="true" /> </tx:attributes> </tx:advice>
<!-- 哪些类的哪些方法参与事务 --> <aop:config> <aop:pointcut id="allManagerMethod" expression="execution(* com.zrgk.service.*.*(..))"/> <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" /> </aop:config> |
13.4继承方式整合
|
public class BaseDaoImpl<T,PK extends Serializable> extends HibernateDaoSupport implements BaseDao<T, PK> { Class entityClass; public Class getEntityClass() { return entityClass; } public void setEntityClass(Class entityClass) { this.entityClass = entityClass; } @Override public void insert(T t) { this.getHibernateTemplate().save(t); } @Override public void update(T t) { this.getHibernateTemplate().update(t); } @Override public void delete(T t) { this.getHibernateTemplate().delete(t); } @Override public T findById(PK id) {
T t = (T)this.getHibernateTemplate().get(entityClass, id); return t; } } |
|
<!-- 配置BaseDao --> <bean id="baseDao" class="com.zrgk.dao.BaseDaoImpl" abstract="true"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> |
13.4保留hibernate配置文件的方式
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"> </property> </bean> |
浙公网安备 33010602011771号