将瞬时对象转换为持久对象(放入一级缓存),hibernate生成insert语句,为瞬时对象设置OID。
不要修改OID,hibernate的更新、删除操作都是通过OID进行。
l 如果程序中出现两个持久对象具有相同OID ,报错:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [cn.itcast.domain.Book#1]
l 操作脱管对象,调用session.update,默认一定产生update语句;
<hibernate-mapping package="cn.cvu.hibernate.domain"> <!-- select-before-update="true",默认false。 当执行update时先查询数据库,对比数据是否发生变化;如果未变化,不执行update --> <class name="PojoUser" table="tb_user" select-before-update="true"> <id> </id> <property> </property> </class> </hibernate-mapping>
public void test() { Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); //此对象和数据库中的内容完全一致 PojoUser user = new PojoUser(); user.setId(1); user.setName("Beyonce"); user.setAge(32); user.setCity("Usa"); //因为POJO.hbm.xml中 select-before-update="true" //hibernate首先执行查询,对比数据库发现数据完全一致,所以不执行下面的update session.update(user); transaction.commit(); session.close(); }
l 执行update操作时,若脱管对象OID在数据库中不存在,会抛出异常:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [cn.itcast.domain.Book#2]
执行此操作时,hibernate会先判断当前对象是否具有OID,然后选择性执行save或者update。对持久化对象无效果。
如果当前对象有OID,进行update操作;如果当前对象没有OID,为null时,一定执行save;进行save操作。
当对象的OID值为POJO.hbm.xml文件配置的unsaved-value值时,将作为瞬时对象,即把这个OID值视为null。
<hibernate-mapping package="cn.cvu.hibernate.domain"> <class name="PojoUser" table="tb_user" select-before-update="true"> <!-- unsaved-value="被视为null的OID值" --> <id name="id" column="t_id" type="int" unsaved-value="0"> <generator class="native"></generator> </id> <property></property> </class> </hibernate-mapping>
public void test() { Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); //设置了OID,是脱管对象 PojoUser user = new PojoUser(); user.setId(0); //OID是0,在数据库不存在 user.setName("Beyonce"); user.setAge(32); user.setCity("America"); //框架获取到对象的OID,执行update。 //但查询后,此OID不存在于数据库,StaleObjectStateException异常。 //在hbm文件配置此OID,被看做null。脱管对象转为瞬时对象,然后被执行save。 session.saveOrUpdate(user); transaction.commit(); session.close(); }
根据id获得持久对象。
1)get立即执行返回目标对象,如果OID不存在则返回null;
2)load延迟加载,首先返回目标类子类对象(代理对象),如果OID不存在则报异常ObjectNotFoundException。
1)delete方法可以删除一个脱管对象,也可以删除持久对象。对象从一级缓存清除后不可继续使用。
2)删除脱管对象时,hibernate先将其变为持久对象,然后执行删除。
- end