首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-10-17 
struts2+hibernate3+spring2读书笔记12(操纵实体对象)第13章 Hibernate操纵实体对象本章导读语在对数据库

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 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());//获得sessionSession session = HibernateSessionFactory.currentSession();//获得事务Transaction ts = session.beginTransaction();//调用Session接口save()访法保存对象//将对象从瞬时态变成持久态session.save(user);//在提交事务之前,数据并没有保存到数据库中//执行如下这句后,会将数据提交到数据库ts.commit();//执行完毕后,关闭sessionHibernateSessionFactory.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{//获得sessionSession 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{//获得sessionSession 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{//获得sessionSession 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字段改为:amigoString 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();//执行完毕后,关闭sessionHibernateSessionFactory.closeSession();}}

热点排行