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

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

[b][size=large]一. 解说Hibernate对象的三种状态[/size][/b]

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

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

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

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

[b] 4.各种状态对象在Hibernate中的转换[/b]

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


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

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

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

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

[b]1. 创建hibernate.cfg.xml文件[/b]
在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>



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

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(){

}

}


[b]3. 编写数据库脚本script.sql[/b]

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='用户信息表


[b]4. 编写User.java[/b]

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;
}
}


[b] 5.配置User.hbm.xml[/b]

<?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>


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

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语句进行记录的插入。


[b]
[size=large]三. 更新实体对象[/size][/b]

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

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

在执行更新前,可通过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()方法执行更新有一个问题,就是需要将所有的必填性都填上,否则会抛出异常。


[b]2. 编写批量更新的测试类:BatchUpdateTest.java[/b]

实现批量更新共有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对象从缓存中清除出去,从而及时释放它占用的内存。


[size=large][b]四. 删除实体对象[/b][/size]

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();

}
}



[b][size=large]五. 绕过Hibernate API对数据进行操作[/size][/b]

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


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();
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值