1,Hibernate初始化类
package com.hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateInit {
private static SessionFactory sessionFactory=null;
//SessionFactory和Configuration对整个应用来说,只有一个实例存在
//为用户访问定义了一个本地线程变量,是静态的,对每一个访问该线程的用户产生一个实例
private static final ThreadLocal<Session> threadlocal=new ThreadLocal<Session>();
static
{
try{
Configuration cfg=new Configuration().configure();
sessionFactory=cfg.buildSessionFactory();
}catch (Exception e)
{
System.out.println("创建会话工厂失败");
e.printStackTrace();
}
}
//要取得Session对象时,首先从当前用户的线程取得Session对象。
//如果还没有创建,从SessionFactory中创建一个Session
//此时会判断SessionFactory对象是否已经创建
//过程:
//首先判断threadLocal中是否存在Session对象
// 如果不存在 则创建Session对象
// 在创建Session对象时 首先要判断系统是否已经加载Configuration
// 如果没有sessionFactory 则需要先创建该对象
// 创建完成的Session对象 需要保存在threadLocal中以供本次访问线程的下一次调用
public static Session getSession() throws HibernateException{
Session session=(Session)threadlocal.get();
if(session==null || !session.isOpen())
{
if(sessionFactory==null)
{
rebulidSessionFactory();
}
session=(sessionFactory!=null)?sessionFactory.openSession():null;
threadlocal.set(session);
}
return session;
}
private static void rebulidSessionFactory() {
try{
Configuration cfg=new Configuration().configure();
sessionFactory=cfg.buildSessionFactory();
}catch (Exception e)
{
System.err.println("创建会话工厂失败");
e.printStackTrace();
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
// 在关闭Session对象是 只需要从当前线程中取得Session对象 关闭该对象 并置空本地线程变量即可
public static void closeSession() throws HibernateException{
Session session=(Session)threadlocal.get();
threadlocal.set(null);
if(session!=null)
{
session.close();
}
}
}
2.保存数据:
1. Session的save()方法是一个临时对象转变成持久化对象
2.完成以下操作:
- 将new对象加入到Session缓存器中,使它进入持久化状态
- 选用映射文件指定标识符生成器,为持久化对象分配唯一的OID,在使用代理主键的情况下,setId()方法为New对象设置的OID使用无效
- 计划执行一条insert语句:在flush缓存的时候
3. Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系. 当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
代码如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class AddProduct {
/**
* 添加商品
*/
public static void main(String[] args) {
Session session = null; //声明Session对象
Product product = new Product();//实例化持久化类
//为持久化类属性赋值
product.setName("Java Web编程宝典");//设置产品名称
product.setPrice(79.00);//设置产品价格
product.setFactory("明日科技");//设置生产商
product.setRemark("无");//无
//Hibernate的持久化操作
try {
session = HibernateInitialize.getSession();//获取Session
session.beginTransaction();//开启事务
session.save(product);//执行数据库添加操作
session.getTransaction().commit();//事务提交
} catch (Exception e) {
session.getTransaction().rollback();//事务回滚
System.out.println("数据添加失败");
e.printStackTrace();
}finally{
HibernateInitialize.closeSession();//关闭Session对象
}
}
}
执行完成后:
注意:持久化状态product在创建后是瞬时状态,在Session执行完save()后,持久化对象product状态变为持久化状态,但这时的数据库操作并没有交给数据库,在事务执行commit()方法后,才完成数据库的添加操作。此时的持久化对象product变为脏数据,Session关闭后,持久化对象product的状态变为游离状态,最后被JVM回收
3.查询数据:
Session对象提供了两种对象装载的方法:get()和load
(1)get()方法
- 如果不缺定数据库中是否有匹配的记录存在,就可以使用get()方法进行对象装载、
- 它会立即访问数据库,如果数据库中没有匹配记录在,会返回null(返回值可能是持久化对象,也可以是null)
- get()方法里面有两个参数:一个持久化对象,另一个是持久化对象中的唯一标识
代码如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class GetProduct {
public static void main(String[] args)
{
Session session=null;
try{
session= HibernateInitialize.getSession();
Product product=(Product)session.get(Product.class,new Integer(0));
System.out.println("产品名称:"+product.getName());
System.out.println("产品价格:"+product.getPrice()+"元");
System.out.println("生产厂商:"+product.getFactory());
System.out.println("产品备注:"+product.getRemark());
}catch (Exception e)
{
System.out.println("对象装载失败");
}finally {
HibernateInitialize.closeSession();
}
}
}
在控制台输出数据,截图如下:
(2)load()方法
返回对象的代理,只有在返回对象被调用时,Hibernate才会发出SQL语句去查询对象
代码如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class LoadProduct {
public static void main(String[] args) {
Session session = null;
try {
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//获取Session
Product product = new Product();//实例化对象
session.load(product, new Integer("0"));//装载对象
//Product product = (Product) session.load(Product.class, new Integer("1"));//装载对象
System.out.println("产品ID:" + product.getId());
System.out.println("产品名称:" + product.getName());
System.out.println("产品价格:" + product.getPrice() + "元");
System.out.println("生产厂商:" + product.getFactory());
System.out.println("产品备注:" + product.getRemark());
} catch (Exception e) {
System.out.println("对象装载失败");
e.printStackTrace();
} finally {
HibernateInitialize.closeSession();//关闭Session
}
}
}
在控制台输出数据,截图如下:
(3)区别:
相同:都可以根据给定的OID从数据库中加载一个持久化类对象
不同点:
- get方法会在调用之后立即向数据库发出sql语句(不考虑缓存的情况下),返回持久化对象;而load方法会在调用后返回一个代理对象,该代理对象只保存了实体对象的id,直到使用对象的非主键属性时才会发出sql语句。
- load()方法返回的是实体的代理类实例,,而get()方法永远返回的是实体类
- 当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null
4.删除数据
(1)Session的delete()方法既可以删除一个游离对象,也可以删除一个持久化对象
(2)处理过程:
- 计划执行一条delete语句
- 把对象从Session缓存中删除,该对象进入删除状态
(3)Hibernate 的 cfg.xml 配置文件中有一个 hibernate.use_identifier_rollback 属性, 其默认值为 false, 若把它设为 true, 将改变 delete() 方法的运行行为: delete() 方法会把持久化对象或游离对象的 OID 设置为 null, 使它们变为临时对象
代码如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class deleteProduct {
public static void main(String[] args)
{Session session = null; //声明Session对象
try {
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//获取Session
session.beginTransaction();
Product product = (Product) session.get(Product.class, new Integer("0"));//装载对象
session.delete(product);//删除持久化信息
session.getTransaction().commit();
} catch (Exception e) {
System.out.println("对象删除失败");
e.printStackTrace();
} finally{
HibernateInitialize.closeSession();//关闭Session
}
}
}
截图如下:
数据库表截图:
注意:在刚增加,查询时都没有开启事务,提交事务,不会报错。但在delete()方法中,是对持久化对象进行删除,当持久化对象发生改动时并不会立即执行数据库操作,只有当事务结束时,才会更新数据库。所以必须使用事务
5.更新数据
(1)从数据库中获得对象,然后修改属性,采用Session的flush()方法--是指Session执行一些必需的SQL语句来把内存中的对象状态同步于JDBC中。刷出会在某些查询之前执行,在事务提交时执行
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//获取Session
Product product = (Product) session.load(Product.class, new Integer("1"));//装载对象
product.setName("Java Web编程词典");//修改商品名称
product.setRemark("无");//修改备注信息
session.update(product );
session.flush();
(2)update()方法
update()方法是一个使一个游离状态转变为持久化对象并且计划执行一条update语句
- 若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update 设为 true. 该属性的默认值为 false
- 当只更新对象一个属性时,其他属性也会被改变,可以把映射文件中 <class> 元素的 dynamic-update设为true
- 当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常
- 当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常.
代码:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class UpdateProduct {
public static void main(String[] args)
{
Session session=null;
try
{
session= HibernateInitialize.getSession();
session.beginTransaction();
Product product=(Product)session.get(Product.class,new Integer(0));
product.setName("Java经典");
session.update(product);
session.getTransaction().commit();
}catch (Exception e)
{
e.printStackTrace();
}finally {
HibernateInitialize.closeSession();
}
}
}
控制台输出截图:
数据库截图:
6.saveOrUpdate()方法
Session 的 saveOrUpdate() 方法同时包含了 save() 与 update() 方法的功能
判定对象为临时对象的标准:
Java对象的OID为null
映射文件中为 <id> 设置了 unsaved-value 属性, 并且 Java 对象的 OID 取值与这个 unsaved-value 属性值匹配
7.merge()方法
新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理:
当ID在数据库中不能找到时,用update的话肯定会报异常,然而用merge的话,就会insert。
当ID在数据库中能找到的时候,update与merge的执行效果都是更新数据,发出update语句;
如果没有设置ID的话,则这个对象就当作瞬态处理:
用update的话,由于没有ID,所以会报异常,merge此时则会保存数据,根据ID生产策略生成一条数据;