天天看点

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

使用Hibernate的“3个准备,7个步骤”

使用环境:Eclipse,MySQL

准备1:导入Hibernate库(jar包);MySQL驱动包;log4j日志包。

Add Library  -- User Library  --  next  --  new user library  --  命名为hibernateJars  --  Add External Jars  --  apply

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

准备2:添加配置文件 --  hibernate.cfg.xml (放在src下)

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
	<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">12345</property>
	<property name="show_sql">true</property>
	<mapping resource="org/hibernate/test/legacy/Simple.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
           

URL:Window -- Show View -- Other -- Data Management -- Data Source Explorer -- Open -- 右键new

选择mysql后next

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

检验url是否正确

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

准备3:添加实体类和映射文件(User.hbm.xml),通常放在一个目录下。

实体类User:

package cn.hrbust.pojo;

import java.sql.Date;

public class User {
	private int id;
	private String name;
	private String gender;
	private int age;
	Date birthday;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}
           

在数据库中创建表T_USER:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

映射文件User.hbm.xml配置:

<?xml version="1.0"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="cn.hrbust.pojo.User" table="T_USER">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <property name="gender"/>
        <property name="age"/> 
        <property name="birthday"/>
    </class>
    
</hibernate-mapping>
           

改hibernate.cfg.xml里的配置

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

七个步骤:

package cn.hrbust.dao;

import java.sql.Date;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;


import cn.hrbust.pojo.User;

public class manageUser {
	public static void main(String[] args) {
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("张三");
		u.setGender("男");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2001-1-1"));
		try {
			cfg =new Configuration().configure();
			sf=cfg.buildSessionFactory();
			session=sf.openSession();
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			session.close();
			sf.close();
		}
		
	}
}
           

运行结果:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

问题解决:

问题1:The word 'localhost' is not correctly spelled

工程中有下划线并提示 The word is not correctly spelled 此问题是Eclipse校验单词拼写造成,如果出在配置文件中,一般会影响到程序的正常执行.

解决方法:

1、在Eclipse下的Window--Preference输入spell

2、然后把第一个复选框“Enable spell checking“给去掉就可以了

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

Hibernate API简介

Hibernate 核心接口:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

Configuration:

概述:Configuration 类负责管理Hibernate 的配置信息。启动Hibernate、创建SessionFactory对象。

1. Hibernate运行的底层配置信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等。

2. Hibernate对象关系映射文件(*.hbm.xml)。

Hibernate配置的两种方法:

1. 属性文件(hibernate.properties)。

调用代码:Configuration cfg = new Configuration();

 2. XML文件(hibernate.cfg.xml)。

调用代码:Configuration cfg = new Configuration().configure();

Configrure()方法默认读hibernate.cfg.xml 

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
	<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">12345</property>
	<property name="hibernate.current_session_context_class">thread</property>
	<!-- 保证每个读写线程有唯一的session实例 -->
	<property name="show_sql">true</property>
	<mapping resource="cn/hrbust/pojo/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
           

SessionFactory:

概述:应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。

1. SessionFactory是线程安全的(Thread-Safe),可以让多个执行线程同时存取SessionFactory而不会有数据共享的问题。

2. 会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。

 3. 需要注意的是SessionFactory是重量级的,因为一 般情况下,一个项目通常只需要一个SessionFactory就够(单例模式),当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

调用代码:SessionFactory sessionFactory = cfg.buildSessionFactory();

Session(会话):

概述: Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流)

1. Session也称为持久化管理器,因为它是与持久化有关的操作接口。

2. Session不是线程安全的,应该避免多个线程共享同一个Session实例。

3. Session通过SessionFactory打开,在所有的工作完成后,需要关闭。

4. 保证在一个线程中仅存在一个Session实例

      1. getCurrentSession (Hibernate 3+)

           getCurrentSession方法,保证了线程中Session的唯一性;

           调用代码: Session session = sessionFactory.getCurrentSession();

           使用getCurrentSession需要在配置文件中加入

           <property name="hibernate.current_session_context_class"> thread </property>

     2. 可以采用ThreadLocal的办法. (Hibernate 2)

     3. 把Session对象放在方法内部定义.

Transaction(事务):

概述: Transaction接口负责事务相关的操作。

它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务,一个JTA用户事务或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。

调用代码:Transaction tx = session.beginTransaction();

    tx.commit();   //提交事务

    …

    tx.rollback(); //回滚事务

注:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。

Query:

概述: Query(查询)接口允许你在数据库上执行查询并控制查询如何执行。查询语句使用HQL或者本地数据库的SQL方言编写。

调用代码:Query query = session.createQuery(“from User”);

单态模式(静态代码块):

package cn.hrbust.dao;

import org.hibernate.HibernateException;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
//SessionFactory单态模式
public class HibernateUtil {
	private static SessionFactory sf=null;
	private static Configuration cfg=null;
//	静态代码块,在类加载的时候只能执行一次
	static {
		try {
			cfg = new Configuration().configure();
			sf = cfg.buildSessionFactory();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static SessionFactory getSessionFactory() {
		return sf;
	}
	public static void closeSessionFactory(){
		sf.close();
	}
}
           

main:

public static void main(String[] args) {
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("李四");
		u.setGender("男");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2001-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

单元测试:

查询用户对象:

//查询用户对象
	public void testQuerySUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			Query query=session.createQuery("from User");
			List<User> users=query.list();
//			for(int i=0;i<users.size();i++)
//			{
//				User u =users.get(i);
//				System.out.println(u.getName()+" "+u.getAge());
//			}
			for(User u: users)
			{
				System.out.println(u.getName()+" "+u.getAge());
			}
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

结果:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

保存用户对象:

//保存用户对象
	public void testSavaUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("张三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			/*
			 * Query query=session.createNamedQuery("from User"); List users=(List)
			 * query.list();
			 */
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

结果:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

自动表生成:

ExportSchema.java:

package cn.hrbust.dao;

import java.util.EnumSet;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;

public class ExportSchema {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//服务注册对象
		ServiceRegistry sr= new StandardServiceRegistryBuilder().configure().build();
		Metadata metadata =new MetadataSources(sr).buildMetadata();
		//创建Schema,表的对象,目的是根据数据生成表
		SchemaExport se=new SchemaExport();
		se.create(EnumSet.of(TargetType.DATABASE), metadata);	
	}

}
           

User.hbm.xml:

<?xml version="1.0"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="cn.hrbust.pojo.User" table="improve">
        <id name="id">
            <generator class="identity"/>
        </id>
        <property name="name" column="username"/>
        <property name="gender" column="sex"/>
        <property name="age" column="age"/> 
        <property name="birthday" column="borndate"/>
    </class>
    
</hibernate-mapping>
           

结果:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

问题:

1.WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

解决办法:

在url的配置中加入?useSSL=false

    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate?useSSL=false</property>

链接: [link](https://blog.csdn.net/qq_40662239/article/details/114532028).
           

2.不能自动创建表

解决办法:

<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

操作实体对象

对象的状态

1.瞬时对象(Transient Objects):由new操作符创建,且尚未与Session 关联的对象被认定为瞬时(Transient)的,不和数据库的数据有任何关联关系。瞬时(Transient)对象没有被持久化到数据库中,也不会被赋予持久化标识(identifier)。

如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。

由于此对象没有纳入Session的管理,那么此时该对象的任何变化都不会发出SQL语句。

可以通过调用Session的持久方法(save(),saveOrUpdate()等)进行持久化操作时才会转变为  持久对象  ,并拥有和数据库记录相同的id标识。

2.持久对象(Persist Objects):持久(Persistent)对象在数据库中有对应的记录,并拥有一个持久化标识(identifier)。

持久对象可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。

它有持久化管理器Session统一管理,持久对象是在事务中进行操作的——Transaction实例执行commit()之后,与数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。

持久化对象任何变化都会自动地发出SQL语句,也就是说该对象和数据库是实时联动(同步的)。

3.托管对象(Detached Objects):与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。托管表示这个对象不能再与数据库保持同步,它们不再受Session管理。

对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached期间的改动将被持久化到数据库)。

本质和瞬时对象相同,都没有纳入Session管理,自身的状态变化,不会自动地发出SQL语句,区别:

 在数据库中有与之对应的记录

 比瞬时对象多了一个数据库标识id

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

Session的缓存

每个Session实例可以看作为一个容器,具有缓存,每一个持久化对象都被纳入Session的缓存中。

数据库中的一条记录在一个Session中只能对应一个对象,不同的Session可以有不同的对象对应数据库中的同一个记录。

Session有如下两个作用:

1.充当蓄水池的作用,减少程序访问数据库的次数。

2.保证缓存中的数据与数据库同步。缓存毕竟不是数据库,它的数据有可能和数据库不一致,这时Hibernate会负责将缓存中的数据同步到数据库。

Session接口操纵实体对象的方法

 save()方法:把Java对象保存数据库中,把一个瞬时对象变成持久对象 。

//保存瞬时用户对象
	public void testSavaUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("张三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		//u此时是瞬时对象,没有对象id,没有纳入session管理,不发sql语句
		u.setName("b");
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			session.save(u);
			//u:持久对象有对象id纳入session管理自动发sql语句
			u.setName("a");//属性改变持久化对象的属性改变发update语句
			ts.commit();
			u.setName("a");//事务提交后,session关闭,属性改变,持久化对象的属性改变不会发update语句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

update()方法:更新数据库中的Java对象,把一个托管对象变成持久对象 。

//托管对象
	public void testDetachedObject(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("张三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
			//在提交之后不执行,u为托管对象,有id,record,但是没有session管理,不发sql语句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		//u: 此时是托管对象,没有session,有id,有record,不自动发SQL语句
		u.setName("赵三");
		u.setAge(100);
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			session.update(u);
			//session.saveOrUpdate(u);
			ts.commit();
			//在提交之后不执行,u为托管对象,有id,record,但是没有session管理,不发sql语句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

delete()方法:把Java对象从数据库中删除,把一个持久对象变成临时对象 。

//删除用户
	public void testDeleteUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			User u=session.get(User.class, 3);
			//持久化对象
			System.out.println(u.getName()+" "+u.getAge());
			//先get再进行其他操作
			session.delete(u);
			//瞬时对象,准确来说是删除对象
			u.setName("c");
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

load()/get()方法:根据对象标识从数据库中加载Java对象,返回的对象都是处于持久化状态。

get()方法:

//查询一个对象
	public void testGetUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			User u=new User();
			u=session.get(User.class, 5);
			//get后是持久化对象
			System.out.println(u.getName()+" "+u.getAge());
			u.setName("老李");
			u.setAge(66);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

saveOrUpdate()方法同时包含了save() 和 update() 两个功能:

1.如果传入的参数是瞬时对象,就调用save()方法。

2.如果传入的对象是托管对象,就调用update()方法。

close()方法,session缓存被清空,缓存中的所有持久化对象都变为游离状态。

evict(): 能够从缓存中删除一个持久化对象,使它变为托管状态。

clear():清除Session中所有缓存对象。

Session的update方法

使一个托管对象转变成持久化对象,重新加入到缓存中。

调用update()方法时,并不立即发送SQL语句,对对象的更新操作将累积起来,在事务提交时,发送一条SQL语句完成全部的更新操作。

使一个托管对象转变成持久化对象,重新加入到缓存中。

class的select-before-update属性;如果想要session仅仅在对象的属性发生变化的时候才执行update,可以把这个属性设置为true。

用于偶尔更改的类,可以用一条select语句防止一条update语句的生成;对于经常更改的类,在每次update语句之前总是要发送一条多余的select语句,反而影响性能。

删除对象——delete

Session的delete方法能够是一个持久化对象或托管对象转变为瞬时状态

对于托管对象,delete方法从数据库中删除与它对应的记录;对于持久化对象,delete方法从数据库中删除与它对应的记录,并把它从session缓存中删除。

装载对象——get 方法 和 load 方法的区别

Session的load()方法和get()方法都能够根据给定的OID(Object ID对象唯一标示符)从数据库中加载一个持久化对象到Session缓存中。

如果没有符合条件的纪录,get返回一个null,load会抛出一个ObjectNotFoundException。

get:

当对象存在时:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

当对象不存在时:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

使用get方法时可以先判断一下对象是否存在

load:

当对象存在时:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

当对象不存在时:

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

get方法立即加载对象, load返回一个代理对象,延迟装载对象,只有在对象第一次被应用程序访问时,Hibernate才会从数据库中加载该对象。

在无法确认持久对象是否存在于数据库中时,开发者应当使用get()方法来获取持久对象,通过判断返回值时候为null来确认持久对象的存在与否。

load、get方法或其它查询方法返回的对象都在session的缓存中。所以如修改对象的属性,那么事务提交后,会将数据同步到数据库。

持久化对象必须唯一

一个Session中不能同时存在两个ID相同的持久化对象

例如:id为userId的user_1对象已经存在Session中,这时如果Session中试图产生一个user_2对象!!

Transaction tx = session.beginTransaction();

User user_1 = (User)session.get(User.class,6);

User user_2 = new User();

user_2.setId(6);

user_2.setUsername("李小四");

session.update(user_2);

最后将会产生异常:net.sf.hibernate.NonUniqueObjectException:

a different object with the same identifier value was already associated with the session

解决办法:再将user_2变为持久化对象之前, 使用evict ()方法将user_1实例从session中去除。session.evict(user_1);

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

session.evict(u);后

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

与数据库的同步

脏数据:数据仅仅在内存中更新而没有同步到数据库中称为脏数据。

hibernate会监测脏数据,在尽可能迟的时候做同步的动作。(transparent transaction-level write-behind)

hibernate可以做到仅仅更新有变动的属性,但是需要在映射文件中设置dynamic-update=“true”,默认是false。这个功能用手工很难完成。

默认更新:更新所有属性

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

设置dynamic-update="true"后

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

对象识别

对数据库而言,其识别一条记录唯一性的方式是根据主键值,如果手上有两条记录,它们拥有同样的主键值,则它们在数据库中代表同一个字段的记录。

对Java而言,要识别两个对象是否为同一个对象有两种方式

内存地址识别(“= =”号识别)

根据equals()、hasCode()中的定义

 (默认Object类中定义的equals(Object o)方法也是按内存地址来比较的),源码如下:

public boolean equals(Object obj){

        return  (this==obj);

  }

先探讨第一种Java的识别方式在Hibernate中该注意的地方,在Hibernate中,如果是在同一个session中根据相同查询所得到的相同记录,则它们会拥有相同的Java识别

举个实际的例子:

Session session = sessions.openSession();

Person p1 = (Person)session.get(Person.class,1);

Person p2 =(Person)session.get(Person.class,1);

session.close(); 

System.out.println(p1 = = p2);

上面这个程序片段将会显示true的结果,表示p1与p2是参考至同一对象

如果是以下的情况则会显示false:

Session session1 = sessions.openSession();

Person p1 = (Person)session.get(Person.class,1);

session1.close(); 

Session session2 = sessions.openSession();

Person p2 = (Person)session.get(Person.class,1);

session2.close(); 

System.out.println(p1 == p2);

使用==来比较两个对象的记录是否代表数据库中的同一条记录是不可行的。如果您要有必要比较通过查询后两个对象的内容是否相同,必须重写 equals()与hashCode()。

重写方法之一,equals()与hashCode()的方法是根据数据库的identity,就是透过getId()方法取得对象的id值并加以比较

例子中假设id的类型是String:

public class Person {   

           ....  

           public boolean equals(Object o) {       

                      if(this == o)

                            return true;      

                      if(id == null || !(o instanceof Person))

                            return false;        

                      final Person person== (Person) o;       

                            return this.id.equals(person.getId());   

}

public int hashCode() {        

return id == null ? System.identityHashCode(this):id.hashcode();   

} 

}
           

然而上面的例子是个不被鼓励的例子,因为当一个对象被new出来而还没有save()时,它并不会被赋予id值,这时候就不适用这个方法。

另一个比较被采用的方法是根据对象中真正包括的属性值来作比较

public class Person {    
 ...    
public boolean equals(Object other) {        
if (this == other) return true;        
if (!(other instanceof Person)) 
	return false;         
final Person Person = (Person) other;         
if (! getUsername().equals(Person.getName())) 
	return false;        
if (!getBirthday().equals(Person.getBirthday())) 
	return false;
if (!getBirthday().equals(Person.getBirthday())) 
     return false;        
return true;    
}     
public int hashCode() {        
int result;        
result = getUsername ().hashCode();        
result = 29 * result + getBirthday().hashCode();      
return result;    
} 
}
           

String对象识别

//String对象识别
	public void testStringObjectIdentify(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			String a="abc";
			String b="abc";
			System.out.println(a==b);
			System.out.println(a.equals(b));
			String c="mnp";
			String d=new String("mnp");
			System.out.println(c==d);
			System.out.println(c.equals(d));
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

User对象识别

//User对象识别
	public void testUserObjectIdentify(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u1=null,u2=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			u1 =session.get(User.class,5);
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory单态模式
			session=sf.getCurrentSession();//保证每个读写线程有唯一的session实例
			ts=session.beginTransaction();
			u2 =session.get(User.class,5);
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		try {
			System.out.println(u1==u2);//同一个session,引用相同
			System.out.println(u1.equals(u2));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
           
Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别

重写hashcode:

public int hashCode() {     
		int result;
		result =getName().hashCode();
		result =29*result + getBirthday().hashCode();
		result =29*result + getAge();
		return result;    }
           

重写equals方法后(在User.java中):

public boolean equals(Object obj) {        
	  if(this == obj) 
	  		return true;       
	  if(obj == null) 
	  		return false;        
	  if(!(obj instanceof User)) 
	  	return false;
	  User other = (User)obj;
	  if(id != other.id)
		  return false;
	  if(age != other.age)
		  return false;
	  if(!name.equals(other.name))
		  return false;
	  if(gender!=null && other.gender!=null) {
		  if(!gender.equals(other.gender))
			  return false;
	  }
	  if(!birthday.equals(other.birthday))
		  return false;
		  return true;
	  }  
           

User对象识别

Hibernate使用Hibernate的“3个准备,7个步骤”Hibernate API简介操作实体对象对象识别