持久化对象的 四种状态

持久化对象的状态













~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. 项目结构


2. hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
    	<property name="hibernate.connection.username">root</property>
    	<property name="hibernate.connection.password">chuck</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.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
    	<property name="hibernate.show_sql">true</property>
    	<property name="hibernate.format_sql">true</property>
    	<property name="hibernate.hbm2ddl.auto">update</property>
    	<property name="hibernate.connection.isolation">2</property>
    	
    	
    	<mapping resource="com/baidu/hibernate/app/Person.hbm.xml"  />
    	
    	
    </session-factory>
    
</hibernate-configuration>
3.持久化类 Person.java
package com.baidu.hibernate.app;

import java.util.Date;

public class Person {
	
	private Integer id;
	private String name;
	private String interest;
	private Date birth;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getInterest() {
		return interest;
	}
	public void setInterest(String interest) {
		this.interest = interest;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public Person() {
		super();
	}
	public Person(String name, String interest, Date birth) {
		super();
		this.name = name;
		this.interest = interest;
		this.birth = birth;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", interest=" + interest
				+ ", birth=" + birth + "]";
	}

}
4. 对象-关系映射 Person.hbm.xml
<?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.baidu.hibernate.app">

    <class name="Person" table="PERSON" >
  
        <id name="id" type="java.lang.Integer" >
            <column name="ID" />
            <generator class="hilo" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="interest" type="java.lang.String">
            <column name="INTEREST" />
        </property>
        
        <property name="birth" type="java.util.Date">
            <column name="BIRTH" />
        </property>
    </class>
    
</hibernate-mapping>
~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~下面是方法测试类~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5. 方法测试类 TestHibernatePerson.java

①  掌握 persist() 和save() 的区别

② 掌握 get() 和load()  的区别

③ 如何才能避免update 方法不盲目的触发 UPDATE 的SQL语句呢? 如何配置

④ saveOrUpdate() 方法 在什么情况下触发 save() 方法,什么情况下触发update() 方法 。什么样的对象也会被视为游离对象?

⑤ 能否 在删除后即把OID 置为空呢? 如何配置


package com.baidu.hibernate.app;

import static org.junit.Assert.*;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernatePerson {
	
	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;
	
	
	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
					.applySettings(configuration.getProperties())
					.buildServiceRegistry();
		
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		System.out.println("init");
	}
	
	@After
	public void destroy(){
		transaction.commit();
		System.out.println("WO  在 commit 后");
		session.close();
		sessionFactory.close();
		System.out.println("distroy");
	}
	
	
	
	/**
	 * 1. save() 方法
	 * 	①. 使一个临时对象变为持久化对象
	 * 	②. 为对象分配ID
	 *  ③. 在flush 缓存时,会发送一条INSERT 语句
	 *  ④. 在save() 方法之前设置的 ID 是无效的
	 *  ⑤. 持久化对象的ID 是不能被修改的
	 * 
	 * save()方式两条sql 语句:
	 * 			 ①.发送一条select 语句
	 * 			 ②. 在发送一条update 语句
	 * 
	 * 执行完save()方法后,执行commit 是 会在发送一条insert 语句
	 */
	@Test
	public void testSave() {
		Person person = new Person();
		person.setName("ZhaoYun");
		person.setInterest("music2");
		person.setBirth(new Date());
		person.setId(20);
		
		System.out.println(person);
		System.out.println("wo zai save 前");
		session.save(person);
		System.out.println("wo zai save 后");
		
		System.out.println(person);
		System.out.println("WO  在 commit 前");
	}
	
	
	/**
	 * persist(): 也会执行INSERT 操作
	 * 
	 *  persist() 和save() 的区别:
	 * 			当对一个OID 不为null 的对象执行save()方法时,会把该对象以一个新的oid保存到数据库中,
	 * 			但是,当执行persist()方法时,则会抛出一个异常
	 */
	@Test
	public void testPersist(){
		Person person = new Person();
		person.setName("Zhao");
		person.setInterest("music");
		person.setBirth(new Date());
//		person.setId(30);//如果在最新persist 方法前的这里 这种的 id 属性,这会抛出异常
						//org.hibernate.PersistentObjectException: detached entity 
						//passed to persist: com.baidu.hibernate.app.Person	
		session.persist(person);
		
		System.out.println("WO  在 commit 前");
	}
	
	/**
	 * get() 和load() 方法
	 * 1. 执行get 方法: 会立即查询加载对象,
	 * 2. 执行load 方法, 若不使用该对象,则不会立即执行查询操作,而返回一个代理对象
	 * 
	 * 		get方法 是立即检索,load 方法是延迟检索。
	 * 
	 * 3. load 方法可能会抛出 org.hibernate.LazyInitializationException: 
	 * 			could not initialize proxy - no Session 异常
	 * 		原因:因为load 是延迟检索,在需要初始化代理对象之前,已经关闭了Session 导致
	 * 
	 * 4. 若数据库中没有对应的记录,session 也没有被关闭:
	 * 		get 返回 null
	 * 		load 若不使用该对象的任何属性,则不会抛异常
	 * 			 若需要初始化时,则会抛出异常。
	 */
	@Test
	public void testLoad(){
		Person person = (Person) session.load(Person.class, 1);
		
		session.close();
		
		System.out.println(person);
	}
	
	@Test
	public void testGet(){
		Person person = (Person) session.get(Person.class, 1);
		//System.out.println(person);
	}
	
	/**
	 * update:
	 * 
	 * 1. 若更新一个持久化对象,不需要显示的调用update() 方法,因为Transaction
	 * 	  的commit() 方法时,会先执行session 的flush 方法。
	 * 
	 * 2. 更新一个游离对象,需要显式的调用session的update方法,只有显示的调用update() 方法,才会把一个游离对象变成了一个持久化对象
	 * 
	 * 3. 如果调用获取对象后,重新设置了对象的属性,但是属性设置前后没有变化,
	 * 		即:数据库中记录id=1 的name属性是 LiuBei, 修改后的name属性 还是LiuBei ,
	 * 		不论是否显示的调用update() 方法,都发送update 的SQL语句 。
	 * 
	 * 注意: 前提: 当显示的调用了update() 方法时:
	 * 	①. 无论要更新的游离对象和数据表中的是否一致,都会发送UPDATE 的 SQL语句。
	 * 		
	 * 		如何才能避免update 方法不在盲目的触发 UPDATE 的SQL语句呢?
	 * 			为了解决这个问题,需要在.hbm.xml 文件的class 中添加 
	 * 			select-before-update=true(默认为false),但通常不需要设置该属性
	 * 			配置详解见下 A
	 * 
	 *  ②. 对于游离对象,可以修改其ID, 但若在数据表中没有和修改后的ID对应的记录,且又调用了update() 方法,则会抛出异常
	 *  						若在数据表中有和修改后的ID对应的记录,且又调用了update() 方法,则会更新数据表中
	 *  						和修改后的ID对应的记录
	 * 		
	 *  ③. 当update() 方法 关联一个游离对象时,如果在Session 的缓存中已经存在相同的OID 的持久化对象,则会抛出异常
	 *  	因为在session 缓存中不能有两个OID 相同的对象同时存在 : 即缓存中不能同时存在两个Id 相同的对象,
	 *  	对应同一条数据库的记录
	 */
	
	@Test
	public void testUpdate(){
		Person person = (Person) session.get(Person.class, 1);
		
		transaction.commit();;
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		person.setName("Liu");
		session.update(person);
		System.out.println(person);
	
	}
	
	
	/**
	 * Session 的 saveOrUpdate() 方法同时包含了 save() 与 update() 方法的功能
	 * 
	 *  判定对象是否为临时对象的标准
	 *  		① Java 对象的 OID 为 null
	 *  		② 映射文件中为 <id> 设置了 unsaved-value  属性, 
	 *  			并且 Java 对象的 OID 取值与这个 unsaved-value 属性值匹配
	 * 			配置详解见下 B
	 * 注意:
	 * 	① 若 OID 不为null, 但是对应该ID的记录,在数据表中又不存在,则会抛出异常:org.hibernate.StaleStateException
	 *  ② 了解:OID 值等于id 的 unsaved-value 属性值的对象,也被认为是一个游离对象。	
	 *  	详解:Person.hbm.xml 配置中 的 id name="id" type="java.lang.Integer" unsaved-value="200"
	 *  		则id=200 的对象会被认为是游离对象
	 *  	
	 */
	@Test
	public void testSaveOrUpdate(){
		Person person = new Person("Tom", "eating fish", new Date());
		person.setId(200);
		session.saveOrUpdate(person);
	}
	
	
	/**
	 *delete: 执行删除操作,只要OID 和数据表中一条记录对应,就会准备执行delete 操作 
	 * 		  若OID 在数据表中没有对应的记录,则会抛出异常
	 * 
	 * 能否 在删除后即把OID 置为空呢? 可以
	 * 		Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性, 其默认值为 false, 
	 * 		若把它设为 true, 将改变 delete() 方法的运行行为:delete() 方法会把持久化对象或游离对象的 OID 
	 * 		设置为 null, 使它们变为临时对象 
	 * 
	 * 		配置详解见下 C
	 */
	
	@Test
	public void testDelete(){
		Person person = new Person();
		//person.setId(851968);//这时person 对象是 当new 的,还未被保存到数据库的数据表中,因此是游离对象
		//session.delete(person);
		
		
		person = (Person) session.get(Person.class, 884736);// 这时person 是从数据库总获取的 是一个持久化对象
		session.delete(person);
	}
	
	
	/**
	 * evict:从session 缓存中把指定的持久化对象移除
	 * 
	 */
	@Test
	public void testEvict(){
		Person person = (Person) session.get(Person.class, 819200);
		Person person2 = (Person) session.get(Person.class, 917504);
		
		person.setName("AA");
		person2.setName("BB");
		
		session.evict(person);
	}
	
	
	/**
	 * Hibernate 如何调用存储过程
	 * 
	 * 可以通过调用 Work 接口 来完成存储过程: 直接通过 JDBC API 来访问数据库的操作
	 * 
	 * Session 的 doWork(Work) 方法用于执行 Work 对象指定的操作, 
	 * 				即调用 Work 对象的 execute() 方法. 
	 * Session 会把当前使用的数据库连接传递给 execute() 方法.
	 * 
	 */
	@Test
	public void testDoWork(){
		
		session.doWork(new Work(){
			
			@Override
			public void execute(Connection connection) throws SQLException {
				System.out.println(connection);
				
			}
		});
	}		
	
}

③ 如何才能避免update 方法不盲目的触发 UPDATE 的SQL语句呢? 如何配置 

详解A:需要在.hbm.xml 文件的class 中添加 select-before-update=true

<?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.baidu.hibernate.app">

	<!-- 
		如何才能避免update 方法不在盲目的触发 UPDATE 的SQL语句呢?
			为了解决这个问题,需要在.hbm.xml 文件的class 中添加 
			select-before-update=true(默认为false),但通常不需要设置该属性
	 -->

    <class name="Person" table="PERSON" select-before-update=true>

        <id name="id" type="java.lang.Integer"  unsaved-value="200">
            <column name="ID" />
            <generator class="hilo" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="interest" type="java.lang.String">
            <column name="INTEREST" />
        </property>
        
        <property name="birth" type="java.util.Date">
            <column name="BIRTH" />
        </property>
    </class>
    
</hibernate-mapping>

④ 调用saveOrUpdate() 方法 什么样的对象也会被视为游离对象?如何配置

详解B:需要在.hbm.xml 文件的id 中配置 

              因为unsaved-value 的值配置为多少 ,这会认为 id = 为多少  的对象也是游离对象,

              如下:unsaved-value=1 ,这id=1  的对象就会被认为也是游离对象

<?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.baidu.hibernate.app">

    <class name="Person" table="PERSON" select-before-update=true>
    	
    	<!-- 
    		OID 值等于id 的 unsaved-value 属性值的对象,也被认为是一个游离对象。
    				
    			例如:<id name="id" type="java.lang.Integer"  unsaved-value="1">
				 因为unsaved-value 的值是1 ,这会认为 id = 1  的对象 也是游离对象    				
    	 -->
    	
        <id name="id" type="java.lang.Integer"  unsaved-value="200">
            <column name="ID" />
            <generator class="hilo" />
        </id>
        
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <property name="interest" type="java.lang.String">
            <column name="INTEREST" />
        </property>
        
        <property name="birth" type="java.util.Date">
            <column name="BIRTH" />
        </property>
    </class>
    
</hibernate-mapping>

⑤ 能否 在删除后即把OID 置为空呢? 如何配置

详解C:需要在hibernate.cfg.xml 文件中配置 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
    	<property name="hibernate.connection.username">root</property>
    	<property name="hibernate.connection.password">chuck</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.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
    	<property name="hibernate.show_sql">true</property>
    	<property name="hibernate.format_sql">true</property>
    	<property name="hibernate.hbm2ddl.auto">update</property>
    	<property name="hibernate.connection.isolation">2</property>
    	
    	<!-- 能否 在删除后即把OID 置为空呢? 可以
    		Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性, 其默认值为 false, 
    		若把它设为 true, 将改变 delete() 方法的运行行为:delete() 方法会把持久化对象或游离对象的 OID 
    		设置为 null, 使它们变为临时对象 
    	 -->
    	<property name="hibernate.use_identifier_rollback">true</property>
    	
    	<mapping resource="com/baidu/hibernate/app/Person.hbm.xml"  />
    	
    	
    </session-factory>
    
</hibernate-configuration>




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值