persist()方法和save()方法对detached态对象的支持

persist()方法不支持detached对象
  • 不管是detached形式一(session close造成),还是detached形式二(new对象 ,setId造成),
  • 不管是在同一事务中(显然同一事务,只支持形式二),还是不同事务中(不同事务支持形式一和二)


同一事务中的操作:

1.Many对象和One对象操作在同一事务中时,
One 对象为持久化对象,
Many对象可正常通过persist()存储入库
        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope71");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");

                DvdType tType = (DvdType) session1.get(DvdType.class, 15);
                QualityType qType =(QualityType) session1.get(QualityType.class, 15);

                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();
            
mysql> select * from DvdTable1;
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
| id | datetime            | description | diskvolume | name        | photo | dvdType_id | qualityType_id |
| 13 | 2010-06-11 21:43:28 | no          |         27 | rope71      | no    |         15 |             15 |
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
11 rows in set (0.00 sec)

2.Many对象和One对象操作在同一事务中时,
One 对象为Transicent对象
Many对象可正常通过persist()存储入库,(同时One对象存储入库)
        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope72");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");

                DvdType tType = new DvdType();
                QualityType qType = new QualityType();
                
                tType.setName("new1");
                qType.setName("new1");
                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();

mysql> select * from DvdTable1;
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
| id | datetime            | description | diskvolume | name        | photo | dvdType_id | qualityType_id |
| 15 | 2010-06-11 21:49:39 | no          |         27 | rope72      | no    |         18 |             18 |
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
13 rows in set (0.01 sec)

mysql> select * from QualityType;
+----+---------------+
| id | name          |
+----+---------------+
| 18 | new1          |
+----+---------------+
17 rows in set (0.00 sec)

mysql> select * from DvdType;
+----+------------+
| id | name       |
+----+------------+
| 18 | new1       |
+----+------------+
17 rows in set (0.00 sec)

3.Many对象和One对象操作在同一事务中时,
One 对象为new对象,但有转成persist对象的资格(其id值对应库表中的存在id),即其符合第二种detached态,它不是trancient 态.
Many对象通过persist()存储入库时,抛出detached entity passed to persist异常

        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope73");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");
                
                DvdType tType = new DvdType();
                tType.setId(2);

                QualityType qType = new QualityType();
                qType.setId(2);
                
                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();

org.hibernate.PersistentObjectException: detached entity passed to persist: com.machome.model.DvdType




不同事务中的操作:

4.Many对象和One对象操作在不同事务中时,
One 对象为Trancient对象
Many对象可通过persist()存储入库

        DvdType tType = new DvdType();
        tType.setName("typetemp 6");

        QualityType qType = new QualityType();
        qType.setName("qualitytemp 6");
            
        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope74");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");

                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();

mysql> select * from DvdTable1;
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
| id | datetime            | description | diskvolume | name        | photo | dvdType_id | qualityType_id |
| 16 | 2010-06-11 22:07:09 | no          |         27 | rope74      | no    |         19 |             19 |
+----+---------------------+-------------+------------+-------------+-------+------------+----------------+
14 rows in set (0.00 sec)


mysql> select * from DvdType;
| 19 | typetemp 6 |


mysql> select * from QualityType;
| 19 | qualitytemp 6 |

5.Many对象和One对象操作在不同事务中时,
One 对象为Persist对象转为detected对象(事务结束)
Many对象通过persist()存储入库时,抛出detached entity passed to persist异常


        Session session = sf.getCurrentSession();
        Transaction tran = session.beginTransaction();
        
        DvdType tType = (DvdType) session.get(DvdType.class, 15);
        QualityType qType =(QualityType) session.get(QualityType.class, 15);
        
        tran.commit();  事务结束
        
        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope73");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");

                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();


org.hibernate.PersistentObjectException: detached entity passed to persist: com.machome.model.DvdType
 

6.Many对象和One对象操作在不同事务中时,
One 对象为new对象,但有转成persist对象的资格(其id值对应库表中的存在id),即其符合第二种detached态,它不是trancient 态.
Many对象通过persist()存储入库时,抛出detached entity passed to persist异常

        DvdType tType = new DvdType();
        tType.setId(2);

        QualityType qType = new QualityType();
        qType.setId(2);
    
        Session session1 = sf.getCurrentSession();
            Transaction tran1 = session1.beginTransaction();
            
                DvdTable1 dvd = new DvdTable1();
                dvd.setName("rope74");
                dvd.setDiskvolume(27);
                dvd.setDatetime(new Date());
                dvd.setDescription("no");
                dvd.setPhoto("no");

                dvd.setDvdType(tType);
                dvd.setQualityType(qType);

                session1.persist(dvd);
                                
            tran1.commit();

org.hibernate.PersistentObjectException: detached entity passed to persist: com.machome.model.DvdType


结论:
对于Many2One One2Many里,对象里包含另一个对象的属性的情况
persist()限制较大,这"另一个对象"必须和当前对象在同一事务中,而且不能符合detached第二种形式(即id不能和数据库中有匹配,即必须是一个新对象)


既然persist()这么多限制,为什么很多场合还要用它而不是save()?
  • 1.persist() 方法更标准,是JPA的标准CRUD方法,可移植性高
比如你在hibernate,JPA,EJB都可采用JPA的标准Annotation, 对persist()方法的支持就比save(),saveOrUpdate()要好.

  • 2.persist()在数据安全性上更可靠
标准文档有如下描述:
persist() also guarantees that it will not execute an INSERT statement if it is
called outside of transaction boundaries. This is useful in long-running conversations
with an extended Session/persistence context.A method like persist() is required.
persist()保证当它在一个transaction外部被调用的时候并不触发一个Sql Insert,这个功能是很有用的,
当我们通过继承Session/persistence context来封装一个长会话流程的时候,一个persist这样的函数是需要的。

比如一个长会话长事务,有可能触发事务的timeout(通常设为几十秒),这样save()很可能发生前事务已经结束(假设没设事务timeout 回滚的话),而这时save()仍然能执行,而这时persist()就无法执行,相对更安全
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值