- 浏览: 236609 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
shuhucy:
必须赞啊,源码理解的很深,解决一个困扰两天的问题
Spring AOP源码分析(八)SpringAOP要注意的地方 -
sealinesu:
精彩
Spring事务源码分析(一)Spring事务入门 -
whlt20090509:
"WEB-INF/view目录下有一个简单的hell ...
SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门 -
hai0378:
兄台 算我一个,最近在研究dubbo motan 及 zk ...
ZooKeeper源码研究寻求小伙伴 -
zpkbtzmbw:
看懂了,原理
SpringMVC源码总结(五)Tomcat的URIEncoding、useBodyEncodingForURI和CharacterEncodingFilter
Session接口方法主要有save、persist、load、get、update、saveOrUpdat、merge、delete等,这里主要是对我看hibernate书籍的一个实践加总结。
首先是save()方法:
以之前的Customer和Order为例,看下类文件:
映射文件Customer.hbm.xml如下:
save方法如下所示:
我们会看到如下的sql语句:
会有一个insert语句和一个update语句。这里的save方法执行时,并没有真正的去执行一条insert语句,而是仅仅从数据库中获取下一个id,并赋值给customer,获取当时customer信息的一个快照,计划执行一条insert语句,然后在事务提交时才会去真正执行该语句,在真正执行前,如果你向数据库中插入一条记录,该记录则会使用下一个id,即customer虽然未向数据库插入,但是已经占据一个id了。执行完该insert语句后会发现当前的customer和已经持久化的customer是不一致的,然后就需要执行一次update语句。
再来看下persist方法
该方法和save()方法的作用是一样的都是将一个临时对象转变为持久化对象。但是它和save的区别下面来介绍:
上述正常情况下和save是一样的,不同之处先来看下官方文档:
这里说明了两点:
第一:persist并不保证一定会给对象的id赋值,这一赋值可能在flush时才会去执行。而save则不同,persist返回void,而save方法是返回id的,即save方法必须从数据库中取出一个可用的id。
第二:persist在事务之外是不会计划执行insert的,而save方法则会计划执行insert的,同时会从数据库中取出一个可用id。
对于第一点,什么情况下persist会为对象的id赋值,我目前还不了解,不再说明。
对于第二点,可做如下实验:
此时并没有开启事务,打印的信息如下:
没有insert语句,同时没有去获取id。
而对于save()方法:
也没有开启事务,打印信息如下:
save方法在没有事务的情况下,仍然计划执行一条insert语句,同时从数据库中获取一个可用id,虽然最终没有insert,但是此id已被占用。
load和get方法
这个比较好理解,get方法始终返回一个真正对象,而load方法则需要根据lazy属性的true和false采用不同的加载策略,当为lazy=true时采用延迟加载的策略,即返回一个代理对象,内部是由javassist来实现代理的。
update方法:
首先使用session1将一个临时对象转化为持久化对象,关闭session1,则该持久化对象变为游离对象(含有主键),通过session2将该游离对象更新为持久化对象。我们可以看到如下sql:
虽然我们有多次set来更新cunstomer的内容,但是最终只有一次update语句。update方法所做的内容是,计划执行一条update语句,但是此时的更新参数并没有确定,只是在事务提交时才会确认更新的参数。这里和save方法就不太一样,save方法计划执行一条insert语句,同时将此时的数据的参数也确定下来了,一旦后面再次更新参数就要执行update语句来更新(见上述save介绍)。
对于update还有一个内容就是,当游离对象属性都没发生改变时,调用update语句仍然会执行一条update语句,如下:
如果想在游离对象没有任何属性更新时就不进行update更新则需要设置select-before-update="true",即在更新前先执行一次查询,通过对比查询出来的数据和现在的数据是否发生变化来决定是否进行update操作。如下设置映射文件:
还是上述同样的程序,执行结果如下:
可以看到先执行一条select语句,然后发现数据并没有发生变化,所以就没有执行update语句。如果数据经常发生变化,则不需要设置select-before-update="true",因为会多于执行一条select语句。
一个session不能拥有两个及以上id相同的对象,一旦拥有一个,然后想保存第二个时就会发生NonUniqueObjectException异常,如下:
在session1关闭时,customer1对象就变为游离对象,然后session2加载了id为customer1对象id的持久化对象作为customer2,此时customer1和customer2的id是一样的,同时customer2已作为session2的持久化对象,此时更改customer1,然后去保存customer1,此时就会抛出NonUniqueObjectException异常,如下:
saveOrUpdate方法:
此方法包含了save和update的功能,当前对象为临时对象时会调用save方法,当前对象是游离对象时调用update方法。它怎么判断当前对象是临时对象和游离对象呢?如果主键id为Integer,则可以判断主键id是否为null来判断,id为null则为临时对象,否则为游离对象。如果主键id为int类型,则需要设置unsaved-value来进行区分,如下:
当对象的id等于unsaved-value值时就为临时对象,否则为游离对象。
merge方法:
对于上述update方法抛出NonUniqueObjectException异常,如果我们想不抛出异常,并且去更新持久化对象,就要使用merge方法,但是merge方法并不局限于此。merger的处理流程如下:
对于merge(customer1):
(1)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果取到则计划执行一条update语句,测试如下:
打印的sql如下:
(2)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果未取到则从数据库中查找出,如果查到则同样更新属性,计划执行一条update语句,此种情况比情况1多了一步向数据库中查询的操作,测试如下:
打印的sql如下:
情况一的查询是我们主动触发的,主要是将数据加载到session2的缓存中,与本情况的查询是不一样的,本情况的查询是因为在缓存中没有对象的持久化对象才触发向数据库中查找。
(3)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果未取到则从数据库中查找出,如果从数据库中也未取到,则会新建一个customer对象,并把customer1的属性复制过去,然后保存该新建的对象,返回该对象的引用,测试如下:
打印的sql如下:
首先是session1从数据库中加载id为100L的数据,然后删除它,关闭session1,则此时customer1则变为游离对象,更改此游离对象,调用merge方法,session2首先从缓存中找id为100L的对象,没有则从数据库中找id为100L的数据,所以会有一条select语句,然后从数据库中也没找到,则session2创建一个新对象customer2,把customer1的属性值复制给customer2,然后insert customer2,所以会有一条insert语句,由于此时customer2是新建的,并不是直接使用的customer1,所以customer1==customer2是false。
(4)如果customer1是临时对象,则同情况三后半部分一样,直接新建一个新的customer对象,然后复制插入,返回新对象的引用,测试如下:
打印的sql如下:
delete方法:
(1)首先是删除一个持久化对象,测试如下:
删除了持久化对象customer1,则从数据库中将其删除,同时将其从session持久化缓存中移除,但是没有删除其id值,真正的删除是发生在session清理缓存的时候,打印的sql如下:
若想在删除一个对象时同时删除其id属性的值,则需要设置hibernate的hibernate.cfg.xml配置文件的hibernate.use_identifier_rollback属性,将其设置为true。同样的测试例子打印的sql如下:
这里有个疑问就是,为什么不把id置为null,而是赋值为0(Customer的id类型为Long类型)。
(2)删除一个游离对象,测试如下:
打印的sql如下:
customer1在session1关闭后成为一个游离对象,具有id值,因此和删除持久化对象的区别并不大,同理设置hibernate.use_identifier_rollback属性将id删除,不再实验。
若想转载请注明出处: http://lgbolgger.iteye.com/blog/2125015
作者:iteye的乒乓狂魔
首先是save()方法:
以之前的Customer和Order为例,看下类文件:
public class Customer { private Long id; private String name; private String email; private Timestamp registeredTime; private Set<Order> orders; //略get、set方法 }
public class Order { private Long id; private String orderNumber; private Customer customer; //略get、set方法 }
映射文件Customer.hbm.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping> <class name="com.ligang.domain.Customer" table="customer"> <id name="id" column="id" type="long"> <generator class="identity"/> </id> <property name="name" column="name" type="string"/> <property name="email" column="email" type="string"/> <property name="registeredTime" column="registeredTime" type="timestamp"/> <set name="orders" cascade="save-update" inverse="true"> <key column="customer_id"/> <one-to-many class="com.ligang.domain.Order"/> </set> </class> </hibernate-mapping>
save方法如下所示:
@Test public void testSave(){ Session session=hibernateDao.getSession(); Transaction tx=session.beginTransaction(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); Timestamp t=new Timestamp(System.currentTimeMillis()); customer.setRegisteredTime(t); session.save(customer); System.out.println(customer.getId()); customer.setEmail("sdfvdf@qq.com"); tx.commit(); session.close(); }
我们会看到如下的sql语句:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) 73 Hibernate: update hibernate.customer set name=?, email=?, registeredTime=? where id=?
会有一个insert语句和一个update语句。这里的save方法执行时,并没有真正的去执行一条insert语句,而是仅仅从数据库中获取下一个id,并赋值给customer,获取当时customer信息的一个快照,计划执行一条insert语句,然后在事务提交时才会去真正执行该语句,在真正执行前,如果你向数据库中插入一条记录,该记录则会使用下一个id,即customer虽然未向数据库插入,但是已经占据一个id了。执行完该insert语句后会发现当前的customer和已经持久化的customer是不一致的,然后就需要执行一次update语句。
再来看下persist方法
该方法和save()方法的作用是一样的都是将一个临时对象转变为持久化对象。但是它和save的区别下面来介绍:
@Test public void testSave(){ Session session=hibernateDao.getSession(); Transaction tx=session.beginTransaction(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); Timestamp t=new Timestamp(System.currentTimeMillis()); customer.setRegisteredTime(t); session.persist(customer); System.out.println(customer.getId()); customer.setEmail("sdfvdf@qq.com"); customer.setName("萨菲您稍等"); tx.commit(); session.close(); }
上述正常情况下和save是一样的,不同之处先来看下官方文档:
这里说明了两点:
第一:persist并不保证一定会给对象的id赋值,这一赋值可能在flush时才会去执行。而save则不同,persist返回void,而save方法是返回id的,即save方法必须从数据库中取出一个可用的id。
第二:persist在事务之外是不会计划执行insert的,而save方法则会计划执行insert的,同时会从数据库中取出一个可用id。
对于第一点,什么情况下persist会为对象的id赋值,我目前还不了解,不再说明。
对于第二点,可做如下实验:
@Test public void testSave(){ Session session=hibernateDao.getSession(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); Timestamp t=new Timestamp(System.currentTimeMillis()); customer.setRegisteredTime(t); session.persist(customer); System.out.println(customer.getId()); customer.setEmail("sdfvdf@qq.com"); customer.setName("萨菲您稍等"); session.close(); }
此时并没有开启事务,打印的信息如下:
null
没有insert语句,同时没有去获取id。
而对于save()方法:
@Test public void testSave(){ Session session=hibernateDao.getSession(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); Timestamp t=new Timestamp(System.currentTimeMillis()); customer.setRegisteredTime(t); session.save(customer); System.out.println(customer.getId()); customer.setEmail("sdfvdf@qq.com"); customer.setName("萨菲您稍等"); session.close(); }
也没有开启事务,打印信息如下:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) 85
save方法在没有事务的情况下,仍然计划执行一条insert语句,同时从数据库中获取一个可用id,虽然最终没有insert,但是此id已被占用。
load和get方法
这个比较好理解,get方法始终返回一个真正对象,而load方法则需要根据lazy属性的true和false采用不同的加载策略,当为lazy=true时采用延迟加载的策略,即返回一个代理对象,内部是由javassist来实现代理的。
update方法:
@Test public void testUpdate(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); session1.save(customer); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); customer.setName("小红"); session2.update(customer); customer.setEmail("917312290小红@qq.com"); tx2.commit(); session2.close(); }
首先使用session1将一个临时对象转化为持久化对象,关闭session1,则该持久化对象变为游离对象(含有主键),通过session2将该游离对象更新为持久化对象。我们可以看到如下sql:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) Hibernate: update hibernate.customer set name=?, email=?, registeredTime=? where id=?
虽然我们有多次set来更新cunstomer的内容,但是最终只有一次update语句。update方法所做的内容是,计划执行一条update语句,但是此时的更新参数并没有确定,只是在事务提交时才会确认更新的参数。这里和save方法就不太一样,save方法计划执行一条insert语句,同时将此时的数据的参数也确定下来了,一旦后面再次更新参数就要执行update语句来更新(见上述save介绍)。
对于update还有一个内容就是,当游离对象属性都没发生改变时,调用update语句仍然会执行一条update语句,如下:
@Test public void testUpdate(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer=new Customer(); customer.setName("小明"); customer.setEmail("917312290@qq.com"); session1.save(customer); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); session2.update(customer); tx2.commit(); session2.close(); }
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) Hibernate: update hibernate.customer set name=?, email=?, registeredTime=? where id=?
如果想在游离对象没有任何属性更新时就不进行update更新则需要设置select-before-update="true",即在更新前先执行一次查询,通过对比查询出来的数据和现在的数据是否发生变化来决定是否进行update操作。如下设置映射文件:
<class name="com.ligang.domain.Customer" table="customer" lazy="true" select-before-update="false">
还是上述同样的程序,执行结果如下:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) Hibernate: select customer_.id, customer_.name as name2_0_, customer_.email as email3_0_, customer_.registeredTime as register4_0_ from hibernate.customer customer_ where customer_.id=?
可以看到先执行一条select语句,然后发现数据并没有发生变化,所以就没有执行update语句。如果数据经常发生变化,则不需要设置select-before-update="true",因为会多于执行一条select语句。
一个session不能拥有两个及以上id相同的对象,一旦拥有一个,然后想保存第二个时就会发生NonUniqueObjectException异常,如下:
@Test public void testUpdate(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer1=new Customer(); customer1.setName("小明"); customer1.setEmail("917312290@qq.com"); session1.save(customer1); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); Customer customer2=(Customer)session2.get(Customer.class,customer1.getId()); customer1.setName("小红"); session2.update(customer1); tx2.commit(); session2.close(); }
在session1关闭时,customer1对象就变为游离对象,然后session2加载了id为customer1对象id的持久化对象作为customer2,此时customer1和customer2的id是一样的,同时customer2已作为session2的持久化对象,此时更改customer1,然后去保存customer1,此时就会抛出NonUniqueObjectException异常,如下:
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.ligang.domain.Customer#98] at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:617) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:301) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244) at org.hibernate.event.internal.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:55) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90) at org.hibernate.internal.SessionImpl.fireUpdate(SessionImpl.java:739) at org.hibernate.internal.SessionImpl.update(SessionImpl.java:731) at org.hibernate.internal.SessionImpl.update(SessionImpl.java:726) at com.ligang.test.dao.CustomerDaoTest.testUpdate(CustomerDaoTest.java:47) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
saveOrUpdate方法:
此方法包含了save和update的功能,当前对象为临时对象时会调用save方法,当前对象是游离对象时调用update方法。它怎么判断当前对象是临时对象和游离对象呢?如果主键id为Integer,则可以判断主键id是否为null来判断,id为null则为临时对象,否则为游离对象。如果主键id为int类型,则需要设置unsaved-value来进行区分,如下:
<id name="id" column="id" type="long" unsaved-value="0"> <generator class="identity"/> </id>
当对象的id等于unsaved-value值时就为临时对象,否则为游离对象。
merge方法:
对于上述update方法抛出NonUniqueObjectException异常,如果我们想不抛出异常,并且去更新持久化对象,就要使用merge方法,但是merge方法并不局限于此。merger的处理流程如下:
对于merge(customer1):
(1)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果取到则计划执行一条update语句,测试如下:
@Test public void testMerge1(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer1=new Customer(); customer1.setName("小明"); customer1.setEmail("917312290@qq.com"); session1.save(customer1); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); Customer customer2=(Customer)session2.get(Customer.class,customer1.getId()); customer1.setName("小红"); session2.merge(customer1); tx2.commit(); session2.close(); }
打印的sql如下:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? Hibernate: update hibernate.customer set name=?, email=?, registeredTime=? where id=?
(2)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果未取到则从数据库中查找出,如果查到则同样更新属性,计划执行一条update语句,此种情况比情况1多了一步向数据库中查询的操作,测试如下:
@Test public void testMerge2(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer1=new Customer(); customer1.setName("小明"); customer1.setEmail("917312290@qq.com"); session1.save(customer1); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); customer1.setName("小红"); session2.merge(customer1); tx2.commit(); session2.close(); }
打印的sql如下:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? Hibernate: update hibernate.customer set name=?, email=?, registeredTime=? where id=?
情况一的查询是我们主动触发的,主要是将数据加载到session2的缓存中,与本情况的查询是不一样的,本情况的查询是因为在缓存中没有对象的持久化对象才触发向数据库中查找。
(3)如果customer1为游离对象,则根据它的id到session缓存中取持久化对象,如果未取到则从数据库中查找出,如果从数据库中也未取到,则会新建一个customer对象,并把customer1的属性复制过去,然后保存该新建的对象,返回该对象的引用,测试如下:
@Test public void testMerge3(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer1=(Customer) session1.get(Customer.class,100L); session1.delete(customer1); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); customer1.setName("小红的妈妈"); Customer customer2=(Customer) session2.merge(customer1); System.out.println(customer1==customer2); tx2.commit(); session2.close(); }
打印的sql如下:
Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? Hibernate: delete from hibernate.customer where id=? Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) false
首先是session1从数据库中加载id为100L的数据,然后删除它,关闭session1,则此时customer1则变为游离对象,更改此游离对象,调用merge方法,session2首先从缓存中找id为100L的对象,没有则从数据库中找id为100L的数据,所以会有一条select语句,然后从数据库中也没找到,则session2创建一个新对象customer2,把customer1的属性值复制给customer2,然后insert customer2,所以会有一条insert语句,由于此时customer2是新建的,并不是直接使用的customer1,所以customer1==customer2是false。
(4)如果customer1是临时对象,则同情况三后半部分一样,直接新建一个新的customer对象,然后复制插入,返回新对象的引用,测试如下:
@Test public void testMerge4(){ Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); Customer customer1=new Customer(); customer1.setName("小红的妈妈"); Customer customer2=(Customer) session2.merge(customer1); System.out.println(customer1==customer2); System.out.println(customer1.getId()); tx2.commit(); session2.close(); }
打印的sql如下:
Hibernate: insert into hibernate.customer (name, email, registeredTime) values (?, ?, ?) false null
delete方法:
(1)首先是删除一个持久化对象,测试如下:
@Test public void testDelete1(){ Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); Customer customer1=(Customer)session2.get(Customer.class,102L); session2.delete(customer1); System.out.println(customer1.getId()); tx2.commit(); session2.close(); System.out.println(customer1.getId()); }
删除了持久化对象customer1,则从数据库中将其删除,同时将其从session持久化缓存中移除,但是没有删除其id值,真正的删除是发生在session清理缓存的时候,打印的sql如下:
Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? 102 Hibernate: delete from hibernate.customer where id=? 102
若想在删除一个对象时同时删除其id属性的值,则需要设置hibernate的hibernate.cfg.xml配置文件的hibernate.use_identifier_rollback属性,将其设置为true。同样的测试例子打印的sql如下:
Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? 0 Hibernate: delete from hibernate.customer where id=? 0
这里有个疑问就是,为什么不把id置为null,而是赋值为0(Customer的id类型为Long类型)。
(2)删除一个游离对象,测试如下:
@Test public void testDelete2(){ Session session1=hibernateDao.getSession(); Transaction tx=session1.beginTransaction(); Customer customer1=(Customer) session1.get(Customer.class,99L); tx.commit(); session1.close(); Session session2=hibernateDao.getSession(); Transaction tx2=session2.beginTransaction(); System.out.println(customer1.getId()); session2.delete(customer1); System.out.println(customer1.getId()); tx2.commit(); session2.close(); System.out.println(customer1.getId()); }
打印的sql如下:
Hibernate: select customer0_.id as id1_0_0_, customer0_.name as name2_0_0_, customer0_.email as email3_0_0_, customer0_.registeredTime as register4_0_0_ from hibernate.customer customer0_ where customer0_.id=? 99 99 Hibernate: delete from hibernate.customer where id=? 99
customer1在session1关闭后成为一个游离对象,具有id值,因此和删除持久化对象的区别并不大,同理设置hibernate.use_identifier_rollback属性将id删除,不再实验。
若想转载请注明出处: http://lgbolgger.iteye.com/blog/2125015
作者:iteye的乒乓狂魔
发表评论
-
hibernate系列(四)一对一关联关系
2014-10-09 07:32 1030以Person类和IDCard类为例,这里仅仅说一种一对一关联 ... -
hibernate系列(三)多对多的关联关系
2014-10-08 06:35 1102以Teacher和Student为例,他们之间是多对多的关系。 ... -
hibernate系列(二)一对多的关联关系
2014-10-07 11:33 1457上一篇文章介绍了基本知识后,本篇该介绍下现实中的一对多的关联关 ... -
hibernate系列(一)hibernate入门
2014-10-06 10:31 1582最近开始学习hibernate,然后就想把这个学习历程总结下来 ...
相关推荐
### Hibernate的核心接口——Session详解 #### 一、Session简述 **1. Session概念** - **定义**: Session 是 Hibernate 框架中最常用的接口之一,它又被称为持久化管理器。Session 负责所有与数据库交互的工作,...
通过`SessionFactory`的`openSession()`方法获得,提供了一系列方法用于执行CRUD(创建、读取、更新、删除)操作。 #### Transaction类 `Transaction`接口用于管理事务边界,确保数据的一致性和完整性。通过`...
**hibernate系列(一)hibernate入门** 在Java世界中,ORM(Object-Relational Mapping,对象关系映射)框架是连接数据库与应用程序的重要桥梁,它将数据库中的数据与程序中的对象进行关联,使得开发者可以使用面向...
`Session`接口提供了多种方法来与数据库交互,如`save()`, `update()`, `delete()`, `get()`, `load()`以及`createQuery()`等。然而,在实际开发中,我们往往需要根据项目需求对其进行定制,例如添加事务管理、异常...
`Session`提供了一系列的事务管理方法,如`beginTransaction()`、`commit()`和`rollback()`。 1. `beginTransaction()`:启动一个新的事务,这通常是所有数据库操作的起点。 2. `commit()`:提交当前事务,意味着...
另外,`Session`还有一系列方法用于处理对象的状态转换,如`lock()`、`merge()`、`refresh()`、`evict()`等,这些方法在处理对象生命周期的不同阶段时非常关键。 `Configuration`和`SessionFactory`也是Hibernate的...
在实际使用中,开发者通常会在一个`Session`生命周期内进行一系列操作,然后在适当的时候调用`flush()`方法强制Hibernate同步数据库,最后在事务结束时调用`commit()`来完成事务。这些方法的正确组合使用是实现高效...
作为Hibernate提供的主要操作数据库的接口,`Session` 不仅承担着保存、更新、删除数据的任务,还负责执行查询操作。更重要的是,`Session` 内部维护了一个缓存机制,该缓存机制能够显著提高数据访问性能,并且能够...
- 使用Hibernate的SessionFactory和Session接口进行数据库会话管理。 - CRUD操作的具体实现:如何通过Hibernate保存(persist)、加载(load/get)、更新(merge)和删除(delete)对象。 - HQL语言的使用,允许以...
- **SessionFactory初始化**:SessionFactory是Hibernate的核心接口,它是线程安全的,用于生成Session实例,它是与数据库进行交互的桥梁。 2. **实现CURD操作** - **创建(Create)**:使用Session的save()或...
4. Hibernate Session:Session是Hibernate用来与数据库交互的接口,它提供了一系列方法来保存、更新、删除和检索持久化对象。Session也负责将对象转换为XML格式存储到文件中。 5. XML序列化与反序列化:将对象数据...
hibernate-session方法是Hibernate框架中与数据持久化密切相关的一系列操作,主要涉及对象/关系映射中的数据管理。在Hibernate中,Session是与数据库交互的主要接口,它扮演着连接ORM(Object-Relational Mapping)...
1. Session接口:是Hibernate的核心接口,代表一次数据库会话。Session提供了添加、更新、删除对象以及执行SQL查询的方法。在事务处理中,通常每个事务对应一个Session实例。 2. Transaction接口:用于管理事务,它...
2. **Session接口**:在`org.hibernate.Session`接口中,定义了与数据库交互的基本操作,如持久化对象、检索对象、事务处理等。它是Hibernate的主要工作接口,实现了对数据库的CRUD(创建、读取、更新、删除)操作。...
5. **Session接口的方法**: - `save()`: 将临时对象转化为持久化对象,分配唯一OID,计划`insert`语句,但不立即执行,直到缓存清理时才执行。如果传入的是持久化对象或游离对象,行为可能不符合预期。 - `update...
Session接口提供了基本的数据操作功能,比如保存、更新、删除和查询对象。Transaction接口用于管理事务,Configuration接口用于配置Hibernate运行环境。 Hibernate4是Hibernate框架的一个版本,它进一步改进了性能...
- `find`系列方法:通过HSQL(Hibernate SQL Query)查询数据,支持带参数和命名参数的查询。 - `findByNamedQuery`:使用预定义的命名查询,提高代码可读性和效率。 4. **增删改查的实现** 这些方法的实现通常...
2. **Session接口**:Hibernate的核心接口,用于与数据库进行交互。Session提供了事务管理、缓存管理和对象的保存、更新、查询等功能。 3. **Query和Criteria API**:提供了一种声明式的方式来执行数据库查询。...
Hibernate 3.3是Hibernate系列的一个里程碑,它引入了诸多新特性,如增强的缓存策略、支持JPA 1.0规范、更灵活的查询语言(HQL)等。这个版本进一步提升了框架的稳定性和可扩展性,使得开发者能够更高效地处理对象与...
在编写代码时,你可以利用Hibernate的Session接口进行增删改查操作,通过SessionFactory创建Session实例。使用Criteria、Query或HQL(Hibernate Query Language)来执行复杂的查询。同时,实体类可以通过注解与...