`
hhr_michael
  • 浏览: 72586 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类
最新评论

struts2+hibernate3+spring2读书笔记12(操纵实体对象)

阅读更多

                                     第13章 Hibernate操纵实体对象
   
本章导读语
      在对数据库进行操作时,常见的操作除了查询外,还有添加、修改和删除记录。本章首先是进了hibernate对象的3种状态,即瞬时态(Transient)、持久态(persistent)、脱管态(Detached)。接关将讲述如何利用Hibernate提供的API来保存、更新和删除对象。另外还讲述了如何绕过Hibernate的API来进行操作。

一. 解说Hibernate对象的三种状态

1. 持久态
             处于持久态的对象在数据库中具有对应的记录,并拥有一个持久化标识。若这两个条件都不满足,该对象将变成瞬时态的对象。当只满足第一个对件时,该对象将变成脱管态对象,持久态对象有两个特点:(1)是和session实例关联。(2)在数据库中有与之关联的记录。

       2.瞬时态
             由new开辟内存空间的java对象,如User user=new User (“hhr”,”男”,”26”),如果没有变量对该对象进行引用,它将被JVM(java虚拟机)回收。处于瞬间态的对象在内存中孤立存在,它是携带信息的载体,但是不和数据库的数据存在任何关联关系。

   3.脱管态
            当与某持久对象关联的session被关闭后,该持久对象转变成为脱管对象,脱管对象有如下特点:

(1) 本质上与瞬时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它收。
(2) 比瞬时对象多了一个数据库记录标识值。

     4.各种状态对象在Hibernate中的转换

(1) 瞬时态—持久态的转换
瞬时态的对象可转为持久态的对象,具体方法是通过session的save()或saveOrUpdate()方法将瞬时对象与数据库关联,并将数据对应地插入数据库中,此时瞬时态变成持久态。


(2) 持久态—瞬时态的转换
                 当对一个持久态的对象使用Hibernate的delete()访法时,将使得处于持久态的对象变成瞬时态。

(3) 持久态—脱管态的转换
                 当一个处于持久态的对象执行session的close()或clear()、evict()之后,该对象将变成脱管态对象,此时该对象虽然具有数据识别值,但它已不在Hibernate持久层的管理之下。

(4) 脱管态—持久态的转换
当脱管态的对象被重新关联上session时,将使得该对象转变成持久态的对象。脱管对象拥有数据库的识别值,可通过update()、saveOrUpdate()等方法转变成持久对象
(5) 脱管态—瞬时态的转换
处于脱管对象执行session的delete()方法,可变成瞬时态的对象。

二. 保存实体对象
在进行关系数据库的操作中,查询、保存、更新和删除记录者是很常用的操作,在Hibernate中,在Hibernate中提供这几个方法都是Session接口.

1. 创建hibernate.cfg.xml文件
在src目录中建立Hibernate的配置文件hibernate.cfg.xml,该文件配置连接本地的MySQL,并加上映射文件User.hbm.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>   
        <!-- 在后台打印sql语句 -->   
        <property name="show_sql">true</property>   
        <!-- 指定sql的本地方言,根据连接的数据库确定-->   
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>      
        <!-- 指定jdbc url,MySql的默认端口为3306,localhost为需要连接的主机,testhibernate为连接的数据库 -->   
        <property name="connection.url">jdbc:mysql://localhost:3306/testhibernate</property>   
        <!-- 数据库的用户名 -->      
        <property name="connection.username">root</property>   
        <!-- 数据库的密码 -->      
        <property name="connection.password"></property>   
        <!-- 设定数据库的驱动类,MySql的驱动jar包为mysql-connector-java-5.0.4-bin.jar,驱动类为com.mysql.jdbc.Driver -->      
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>   
      
        
        <!--指定0到多个hbm.xml映射文件-->   
        <mapping resource="amigo/hibernate/operate/User.hbm.xml" />   
        
    </session-factory>   
</hibernate-configuration>  
  


2. 编写Session工厂类:HibernateSessionFactory.java(该类提供了获取当前session的关闭session的方法),具体代码如下:

package amigo.hibernate.operate;   
  
import org.hibernate.HibernateException;   
import org.hibernate.Session;   
import org.hibernate.SessionFactory;   
import org.hibernate.cfg.Configuration;   
import org.apache.log4j.*;  
/**  
 * Hibernate的session获取类.  
 * */  
public class HibernateSessionFactory {   
	
	public static Logger log=(Logger)Logger.getLogger(HibernateSessionFactory.class);
	private static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";  
       
    /**持有一个单态的Session实例.*/  
    private static final ThreadLocal threadLocal=new ThreadLocal();   
       
    /**持有一个单态的configuration实例.*/  
    private static final Configuration cfg=new Configuration();   
       
    
    private static SessionFactory sessionFactory;    
  
       
    /**  
     * 获得当前的Session实例  
     * */  
    public static Session currentSession() throws HibernateException{   
        Session session = (Session)threadLocal.get();   
        if(session==null||session.isOpen()==false){   
            if(sessionFactory==null){   
                try{   
                    cfg.configure(CONFIG_FILE_LOCATION);   
                    sessionFactory=cfg.buildSessionFactory();   
                }   
                catch(Exception e){  
                	log.error(e);
                    log.error("Error Creating SessionFactory%%%%"+session.isOpen());   
                       
                }      
            }   
            session=sessionFactory.openSession();   
            threadLocal.set(session);   
        }   
        return session;   
    }   
    /**关闭session*/
    	public static void closeSession() throws HibernateException{
    		Session session=(Session) threadLocal.get();
    		threadLocal.set(null);
    		if(session !=null){
    			session.close();
    			
    		}
    	}
         private HibernateSessionFactory(){
        	 
         }
    
}  


3. 编写数据库脚本script.sql

CREATE DATABASE `testhibernate`;
USE `testhibernate`;

#创建用户信息表
CREATE TABLE `tbl_user` (
  `loginName` varchar(50) NOT NULL COMMENT '用户登录名',
  `name` varchar(50) NOT NULL COMMENT '姓名',
  `password` varchar(50) NOT NULL COMMENT '登录密码',
  `createTime` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY  (`loginName`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 COMMENT='用户信息表


4. 编写User.java

package amigo.hibernate.operate;

import java.io.Serializable;

/**
 * 用户信息pojo类
 * */
public class User implements Serializable {
		private static final long serialVersionUID=1L;
		
		/**登录名,主键*/
		private String loginName;
		
		/**姓名*/
		private java.lang.String name;
		/**密码*/
		private String password;
		/**创建时间*/
		private java.util.Date createTime;
		public String getLoginName() {
			return loginName;
		}
		public void setLoginName(String loginName) {
			this.loginName = loginName;
		}
		public java.lang.String getName() {
			return name;
		}
		public void setName(java.lang.String name) {
			this.name = name;
		}
		public String getPassword() {
			return password;
		}
		public void setPassword(String password) {
			this.password = password;
		}
		public java.util.Date getCreateTime() {
			return createTime;
		}
		public void setCreateTime(java.util.Date createTime) {
			this.createTime = createTime;
		}
}


5.配置User.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 package="amigo.hibernate.operate">
<class name="User" table="tbl_user">
	<id name="loginName" column="loginName" type="java.lang.String">
		<generator class="assigned"/>
	</id>
	
	<property name="name" column="name" type="java.lang.String" not-null="true"/>
	<property name="password" column="password" type="java.lang.String" not-null="true"/>
	<property name="createTime" column="createTime" type="java.util.Date" not-null="true"/>
	
	
	
</class>
</hibernate-mapping>


6.编写保存实体对象测试类:SaveTest.java

package amigo.hibernate.operate;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;



/**测试利用Session接口的方法保存对象*/
public class SaveTest {
		public static void main(String[] args)throws Exception{
			//瞬时态对象
			User user = new User();
			//设置对象的属性
			user.setLoginName("amigo");
			user.setName("阿密果");
			user.setPassword("198211");
			user.setCreateTime(new Date());
			//获得session
			Session session = HibernateSessionFactory.currentSession();
			//获得事务
			Transaction ts = session.beginTransaction();
			
			//调用Session接口save()访法保存对象
			//将对象从瞬时态变成持久态
			session.save(user);
			//在提交事务之前,数据并没有保存到数据库中
			//执行如下这句后,会将数据提交到数据库
			ts.commit();
			//执行完毕后,关闭session
			HibernateSessionFactory.closeSession();
			System.out.println("保存成功!");
		}
}


备注:保存对象除了可调用Session接口的save()外,还可以调用该接口的saveOrUpdate()方法,该方法首先使用select语句查询是否有loginName与之相同的记录存在,若存在,则执行update语句对该记录进行更新操作,若不存在,则执行insert语句进行记录的插入。



三. 更新实体对象


Sessin接口提供了update()和saveOrUpdate()方法来更新单个实体对象。在更新对象实体前,一般是通过load()或get()方法获得对象后再执行更新。

1. 编写更新单个实体对象测试类:UpdateTest.java

在执行更新前,可通过load()或get()方法获得对象,而后更新属性后,通过Session接口的update()方法进行更新。

package amigo.hibernate.operate;

import org.hibernate.Session;
import org.hibernate.Transaction;



/**
 * 测试利用Session接口方法更新对象
 * */
public class UpdateTest {
		public static void main(String[] args)throws Exception{
				//获得session
			Session session= HibernateSessionFactory.currentSession();
				//获得事务
			Transaction ts = session.beginTransaction();
			
				//获得持久化对象
			String loginname = "amigo";
			User user = (User)session.get(User.class, loginname);
			
			//更新对象的属性
			user.setName("hhr");
			user.setPassword("123456");
			
			session.update(user);
			
			ts.commit();
			HibernateSessionFactory.closeSession();
			System.out.println("更新成功!");
		}
}

备注:Session接口的load()和get()方法都可以根据给定的OID从数据库中加载对象,两者的不同是当对象不存在时,get()方法返回null,而load()方法将抛出org.hibernate.ObjectNotFoundException异常。另外,还可以使用saveOrUpdate()方法执行更新有一个问题,就是需要将所有的必填性都填上,否则会抛出异常。


2. 编写批量更新的测试类:BatchUpdateTest.java

实现批量更新共有4种方法,分别是:
(1) 使用存储过程进行批量更新。
(2) 绕过Hibernate API,直接通过JDBC API进行数据的批量更新。
(3) 查询出需要更新的对象后,遍历这些对象,循环使用update()方法进行更新。
(4) 使用createQuery(String hql)方法获得Query对象后,设置参数后,执行executeUpdate()方法更新记录。

package amigo.hibernate.operate;

import java.util.Iterator;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;


/**
 * 批量更新对象
 * */
public class BatchUpdateTest {
			public static void main(String[] args)throws Exception{
					//获得session
					Session session = HibernateSessionFactory.currentSession();
					//获得事务
					Transaction ts = session.beginTransaction();
					//第3种方式批量更新数据
					//将所有loginname中包含amigo的记录的name都改为"阿密果"
					Query queryUpdate = session.createQuery("from User where loginname like ?");
					queryUpdate.setParameter(0, "%amigo%");
					
					//循环更新数据
					Iterator users = queryUpdate.list().iterator();
					int count=0;
					while(users.hasNext()){
						User user = (User)users.next();
						user.setName("阿密果");
						session.flush();
						session.evict(user);
						count++;
						
					}
					System.out.println("使用第3种方式批量更新记录条数为="+count);
					
					//第4种方式批量更新数据
					//将所有loginname中包含xiexx的记录的name都修改为"amigo"
					
					String hqlUpdate="update User set name=? where loginname like ?";
					Query query = session.createQuery(hqlUpdate);
					query.setParameter(0, "amigo");
					query.setParameter(1, "%xiexx%");
					int updateCount = query.executeUpdate();
					System.out.println("使用第4种方式批量更新记录条数为="+updateCount);
					ts.commit();
					HibernateSessionFactory.closeSession();
			}
}

备注:在使用第3种方式更新一个User对象的name属性后,就立即调用Session的flush()方法和evict()方法。Flush()方法使Hibernate立刻根据这个User对象的状态变化同步更新数据库,从而立即执行相关折update语句evict()方法用于把这个Customer对象从缓存中清除出去,从而及时释放它占用的内存。


四. 删除实体对象

package amigo.hibernate.operate;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;


/**
 * 测试利用Session的接口的方法来删除对象
 * */
public class DeleteTest {
		public static void main(String[] args)throws Exception{
				//获得session对象
			  Session session = HibernateSessionFactory.currentSession();
			  	//获得事务
			  Transaction ts = session.beginTransaction();
			  
			    //获得持久化对象
			  String loginname="amigo";
			  User user = (User)session.get(User.class,loginname);
			  
			  //删除单个对象
			  session.delete(user);
			  System.out.println("删除成功!");
			  
			  //删除所有loginname包含xiexx的记录
			  String hqlDelete ="delete User where loginname like ?";
			  Query query = session.createQuery(hqlDelete);
			  query.setParameter(0, "%xiexx%");
			  int deletecount = query.executeUpdate();
			  System.out.println("批量删除记录条数为="+deletecount);
			  
			  ts.commit();
			  //执行完毕后,关闭session
			  HibernateSessionFactory.closeSession();
			  
		}
}



五. 绕过Hibernate API对数据进行操作

编写使用JDBC APIFJP 进行数据操作的类:jdbcTest.java


package amigo.hibernate.operate;

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.hibernate.Session;
import org.hibernate.Transaction;


/**
 * 使用JDBC API进行数据操作
 * */
public class JdbcTest {
		public static void main(String[] args)throws Exception{
			//获得session
			Session session = HibernateSessionFactory.currentSession();
			//获得事务
			Transaction ts = session.beginTransaction();
			//通过Session的Connection()方法获得Connection对象
			//该方法已不推荐使用
			Connection con = session.connection();
			
			//添加数据
			String insertSql="insert into tbl_user(loginname,name,password,createTime)"+"value('amigoxx','amigoxx','123','2008-8-3')";
			PreparedStatement stmtInsert = con.prepareStatement(insertSql);
			stmtInsert.executeUpdate(insertSql);
			System.out.println("添加成功!");
			
			//修改数据
			//将所有longinname为amigo的数据的name字段改为:amigo
			String updateSql="update tbl_user set name='amigo' where loginname like '%amigo%'";
			PreparedStatement stmtUpdate=con.prepareStatement(updateSql);
			stmtUpdate.executeUpdate(updateSql);
			System.out.println("修改成功!");
			
			//删除数据
			//删除所有loginname为xiexx的数据
			String deleteSql="delete from tbl_user where loginname like '%xiexx%'";
			PreparedStatement stmtDelete = con.prepareStatement(deleteSql);
			stmtDelete.executeUpdate(deleteSql);
			System.out.println("删除成功!");
			
			//提交事务
			ts.commit();
			//执行完毕后,关闭session
			HibernateSessionFactory.closeSession();
		}
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics