欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate持久层框架学习笔记

程序员文章站 2022-04-16 22:46:43
...

Hibernate持久层框架

orm映射框架 orm映射器模式,由一系列的java类和配置文件形成。

hiberanate下对象的三种形态

  • 瞬态:对象由new操作符创建,且尚未与Hibernate Session关联的对象,被认为处于瞬态。瞬态对象不会被持久化到数据库中,也不会被赋予持久化标示,如果程序中失去了瞬态对象的引用,瞬态对象将被垃圾回收机制销毁。使用Hibernate session可以让其变为持久化状态。

  • 持久化:持久化实例在数据库中有对应的记录,并拥有一个持久化标识(identifier),持久化的实例可以是刚保存的。也可以是刚被加载的。无论那种,持久化对象都必须与指定的Hibernate Session关联。Hibernate会检测到处于持久化状态对象的改动,在当前操作执行完成时将对象数据写回数据库。开发者不需要手动执行UPDATE。

  • 游离:某个实例曾经处于持久化状态,但随着与之关联的session被关闭,该对象就变成游离状态了。游离对象的引用依旧有效,对象可以继续被修改,只是不会同步到数据库中。如果重新让游离对象与某个session关联,该对象会重新转换为持久化状态。

UserBean.hbm.xml,对bean类的属性映射

//一个简单对象的orm映射
<class name="路径" catalog="hibernate" table="long"> 
 <id name="id" column="id" type="">
    //hibernate框架中。常见的id生成方案有:
    identity 自增长(数据库),程序和框架不负责Id的产生
    increment 自增长(框架),先查max(id),然后再+1,作为自增长的id
    assigned 程序负责id的生成,调用对象的.setId()去生成id。框架与数据库不负责此时id的生成
    uuid.hex 将ip地址,mac地址,时间搓等一系列不容易重复的元素按照一定的算法生成一个32为不重复的字符串()
    foreign 外来的,通常适用于主键一对一模式(比如两张表的id是一样的)
 
    <generator class="identity"></generator>
    </id>
    
    <property nam   e="userName" column="user_name" type="string" length="20"></property>
    <property name="password" column="password" type="string" length="32"></property>
	<property name="loginName" column="login_name" type="string" length="32"></property>
	<property name="age" column="age" type="int"></property>
	<property name="birthday" column="birthday" type="java.util.Date"></property>

hibernate.cfg.xml,hibernate的配置文件

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

<hibernate-configuration>
<!-- 配置Hibernate的SessionFactory -->
<session-factory>

	<!-- 定义hibnerate操作数据库的方言 -->
	<property name="dialect">
		org.hibernate.dialect.MySQLDialect
		<!-- org.hibernate.dialect.OracleDialect -->
		<!-- org.hibernate.dialect.SQLServerDialect -->
	</property>

	<!-- 定义JDBC连接数据库,最基本的4大元素 -->
	<property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
	<property name="connection.url">jdbc:mysql://localhost:3306/hibernate?characterEncoding=UTF-8</property>
	<property name="connection.username">root</property>
	<property name="connection.password">lovo</property>
	
	<!-- 上述4个元素可以让JDBC,获取mysql数据库连接,但是连接取回来之后,需要放置在C3P0连接池 -->
	<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
	<property name="hibernate.c3p0.max_size">50</property><!-- 最大连接数定义为:50 -->
	<property name="hibernate.c3p0.min_size">5</property><!-- 最小连接数定义为:50 -->
	<property name="hibernate.c3p0.timeout">10000</property><!-- 配置连接超时时间,单位:毫秒 -->
	<property name="hibernate.c3p0.max_statements">200</property><!-- 连接池中可以缓存的最大预编译对象的个数为200 -->
	<property name="hibernate.c3p0.acquire_increment">5</property><!-- 当连接池中,连接不够时,需要再次获取的连接数量 -->
	<!-- 配置hibernate关于显示SQL的相关配置 -->
	<property name="show_sql">true</property>
	<!-- 按SQL规范来显示SQL语句 -->
	<property name="format_sql">true</property>
	<!-- 告知XXX.hbm.xml配置文件 -->
	<mapping resource="org/framestudy/hibernatexmls/xmls/UserBean.hbm.xml"/>
</session-factory>
</hibernate-configuration>

applicationContext.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    //main里所有的包文件
 <context:component-scan base-package="org.framestudy.hibernatexmls"/>
  
 <aop:aspectj-autoproxy/>
</beans>

get和load方法:

  • get和load都是hibernate提供的根据id查询对象的方案,但是有所区别,它们的查询顺序不一致,

    • get先查一级缓存再查二级缓存最后没有的话查数据库,get方法返回的是真实对象。
    • load先查一级缓存再查二级缓存,如果二级没有则不会查询数据库,而是默认数据库中一定存在这条数据,所以返回了一个动态代理对象(只有返回了动态代理对象才会去查询真实对象),但使用这个动态代理对象时,将会去查询数据库。
  • get方法较为常见一些。对象与session关联时,一定会在session对应的缓存空间里,session提交或关闭时会把里面的内容清理掉。

例子

在库里面有二这条数据,即使数据库删除了这条数据,只要不打印这个方法,load依然默认这个数据在。

在hibernate直接写from等同于select * from   
hql===hibernate query language是一种面向对像的查询语句   
在hibernate中如果以问号来传值我们称之为:位置设值方案(起始位置为0);还有一种参数设值方案,或者叫做参数别名设值方案  

String hql="from......like concat(?,‘%’)" //:位置设值方案  
String hql="from    like concat(:username,'%')" //参数别名设值方案  
//第一个创建一个Query接口实例,第二个就是将上述的HQL转换成SQL,并且对SQL进行预编译。 
Query query=session.createQuery(hql); 
//在jdbc中第一个问号起始值为1,但是在hibernate中起始位置为0,给0号位置设置具体的值。 
query.setString(0,userName)   
 query.setString(“username”,userName)//参数别名设值方案    
//sql的代码操作  
String sql="select * from.....like concat(?,'%')";
//是将sql查询出来的结果向对象进行转换。 
SQLQuery query=session.createQuery(sql);    
query.setString(0,userName)   
query.addEntity(UserBean.class);

return query.list();返回的是个对象,例如List<?>    

可以通过new构造的方式,实现想查几列数据就查几列数据   
String hql="select new Map(列名,列名)  from 表名 where...."   

如果传多个参数或一个bean对象  
使用setProperties()方法 两种传值方式:     
多参数在批量设值的情况下,封装成对象,要求对像的属性名与参数名保持一致  
多参数在批量设值的情况下,封装成map集合,要求map的键名与参数名保持一致

Criteria 该接口与Query接口一样,主要用条件查询
条件查询的例子
单参数查询

public List<?> findUsersByUserName(String userName) {
	// TODO Auto-generated method stub
 /*		
	//在Hibernate中,如果以?来传值,我们称之为:位置设值方案(起始位置是0)
	//hql === hibernate query language (一种面向对象的查询语句)
	//在Hibernate中,直接写From === select * from 
	String hql = "From UserBean as u where u.userName like CONCAT(?,'%')";
	//这句话的作用:第一个创建一个Query接口实例,第二个就是将上述的HQL转换成SQL,并且对SQL进行预编译
	Query query = session.createQuery(hql);
	//在JDBC中,第一个?起始值为1,但是在hibernate中,起始位置为0
	query.setString(0, userName);*/
	
	
/*	//在Hibernate中,除了可以使用?传值方案以外,还有一种:参数别名设值方案
	String hql = "From UserBean as u where u.userName like CONCAT(:userName,'%')";
	Query query = session.createQuery(hql);
	query.setString("userName", userName);*/
	
	
	
 /*		String sql = "select * from t_user where user_name like CONCAT   (?,'%')";
	SQLQuery query = session.createSQLQuery(sql);
	query.setString(0, userName);
	query.addEntity(UserBean.class);//是将通过SQL查询出来的结果,向对象进行转换
	return query.list();*/
	
	
 /*		
 * 可以通过new 构造的方式,实现想查什么就查什么,但是可能会导致构造非常复杂
 * 
 * String hql = "select new UserBean(u.loginName,u.password) "
                +"from UserBean as u where u.userName like CONCAT(?,'%')";
	Query query = session.createQuery(hql);
	query.setString(0, userName);
	return query.list();*/
	
	
	String hql = "select new map(u.loginName as loginName,u.password as password) "
                      +" from UserBean as u where u.userName like CONCAT(?,'%')";
	Query query = session.createQuery(hql);
	query.setString(0, userName);
	return query.list();
}

多参数查询(参数是一个类对象)

/**
 * 多参数在批量设值的情况下,要求对象的属性名与参数别名保持一致
 */
@Override
public List<?> findUsersByUser(User user) {
	// TODO Auto-generated method stub
	String hql = "from UserBean as u "
                     +" where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
	Query query = session.createQuery(hql);
	query.setProperties(user);
	return query.list();
}

多参数查询(参数是一个Map集合)

/**
 * 多参数在批量设值的情况下,要求Map键值对中的键与参数别名保持一致
 */
@Override
public List<?> findUsersByMap(Map params) {
	// TODO Auto-generated method stub
	String hql = "from UserBean as u "
                  +" where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
	Query query = session.createQuery(hql);
	query.setProperties(params);
	return query.list();
}

(参数是一个Map集合)分页查询(参数是一个Map集合和一个类)

public PageBean findUsersByMap2PageBean(PageBean pager, Map params) {
	// TODO Auto-generated method stub
	//Criteria 该接口与Query接口一样,同样可以用作条件查询,但是它没有Query接口灵活
	//主要存在的问题:HQL的结构不清晰,不可以实现 “按需查询(想查什么, 就查什么)” 
	//所以推荐大家,多条件查询时,还是用结构比较清晰的Query接口
	
	/*//第一个步骤(查询满足条件的总的条数)
        
	Criteria criteria = session.createCriteria(UserBean.class);// === From UserBean 
        // === userName like CONCAT(params.get("userName").toString(),'%')
	criteria.add(Restrictions.like("userName", params.get("userName").toString(), MatchMode.START));
        
	criteria.add(Restrictions.eq("age", params.get("age")));
        // === password = params.get("password")
	criteria.add(Restrictions.eq("password", params.get("password")));
        // === id >= 20 注意:属性是什么类型,那么你在传值的时候,就传递什么类型
	criteria.add(Restrictions.ge("id", 20l));
	criteria.setProjection(Projections.count("id"));//在From UserBean 前方 添加select count(id)
	long totalRows = (long) criteria.uniqueResult();
	pager.setTotalRows(totalRows);
	
	//第二个步骤(查询具体的数据)
	criteria.setProjection(null);//取消HQL投影(干掉我们自己HQL语句前面添加的max,min,count……数据库方法)
	criteria.setFirstResult(pager.getIndex());
	criteria.setMaxResults(pager.getRows());
	List<?> datas = criteria.list();
	pager.setDatas(datas);
	return pager;*/
	
	
	
	//第一个步骤(查询满足条件的总的条数)
	String hql = "select count(u.id) 
                      from UserBean as u 
                      where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
	Query query = session.createQuery(hql);
	query.setProperties(params);
	long totalRows = (long) query.uniqueResult();
	pager.setTotalRows(totalRows);//设置总条数
	//第二个步骤(查询具体的数据)
	hql = "select new map(u.loginName as loginName,u.password as password) 
               from UserBean as u 
               where u.userName like CONCAT(:userName,'%') and u.age = :age and u.password = :password";
	query = session.createQuery(hql);
	query.setProperties(params);
	query.setFirstResult(pager.getIndex());//在设置index
	query.setMaxResults(pager.getRows());//在设置rows
	List<?> datas = query.list();
	pager.setDatas(datas);
	return pager;
}

为什么要用缓存

mysql的数据性能不高,主要体现在连接(不能支持过多的连接,当数据量的数据过多,查询的列上没有添加索引,查询数据是非常慢的)

1.本地缓存:和应用程序耦合在同一台机器的缓存技术。缺陷是会和应用程序争抢内存空间。如果缓存过大会抛出缓存不足的内存异常。任何一个持久层框架的一级和二级都是本地缓存。本地缓存读写比例比较高,不会经常更改,并发修改的机会不能过多,不能缓存大容量数据。 缓存过多会和应用程序争抢应用空间。
又称事务级缓存,由hibernate的session提供, 缓存空间的生命周期同session保存一致。

2.分布式缓存: 和应用程序处于不同区域上的缓存技术。分布式缓存那些集群的服务器与服务器之间不会做数据同步。 分布式缓存可以存储大容量数据。绝大多数的系统80%以上的操作都是针对的20%的核心数据。符合读写比例高的数据才有必要缓存起来。
又被称为应用级缓存,由sessionFacotory提供。

由同一个sessionFacotory创建的session的实例共享缓存空间。 需要手动开启。session刷新(提交和关闭时)时把数据刷新到二级缓存中。hibernate一般不用二级缓存,一般sessionfacotry的职责是创建session,又分配给他缓存职责的让它去维护session对象的话会影响它的性能。

二级缓存分为对象缓存和查询缓存:按照对象和id的存储方式的缓存;query的缓存,编译后的sql语句和结果集。
本地缓存不使用这个方法,分布式缓存用

ehcache.xml关于二级缓存文件的配置

<ehcache>
<!-- <diskStore path="java.io.tmpdir"/> 是指数据放置在内存的临时目录中,
如果内存空间过小,我们还可以将数据存入到硬盘上,例如:<diskStore path="d:/cache"/> -->
<diskStore path="java.io.tmpdir"/>

<defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true"
    memoryStoreEvictionPolicy="LRU"
    />
    
    <!-- maxElementsInMemory="10000" 缓存中,允许放置的最大缓存对象的个数-->
    <!-- eternal="false" 表示缓存的对象,是否需要持久化到硬盘中 -->
    <!-- timeToIdleSeconds="120" 表示空闲的缓存对象,在缓存空间中,可以存活的时间,单位是S -->
    <!-- timeToLiveSeconds="120" 表示缓存对象的钝化时间,设置使用过的缓存对象,重新给它设置一个复活时间 -->
    <!-- overflowToDisk="true" 当内存空间不足时,是否将数据保存到硬盘中去 -->
    <!-- memoryStoreEvictionPolicy="LRU" 当缓存空间不足时,可以采用以下算法来为新的缓存数据,清理缓存空间:
    FIFO first in first out  先进先出
    LRU Least Recently Used  最近最少时间
    LFU Less Frequently Used 最少使用(从缓存建立起来开始算,最少使用,就优先清理掉)
     -->
</ehcache>

在hibernate.cfg.xml文件中加入如下代码配置二级缓存

<!-- 手动开启二级缓存功能 -->
	<property name="cache.use_second_level_cache">true</property>
	<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
	<property name="hibernate.cache.use_query_cache">true</property>

对某个bean文件orm映射时创建的xml文件内容(以addressBean为例)

//非注解版
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 //catalog是指数据库名
 <hibernate-mapping>  
<class name="org.framestudy.hibernatexmls.beans.AddressBean" catalog="hibernate" table="t_address">
	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	
	<property name="address" column="address" type="string" length="120"></property>
</class>

</hibernate-mapping>

非注解版一对多
classBean的配置

<?xml version="1.0" encoding="UTF-8"?>
<!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="org.framestudy.hibernatexmls.beans.StudentBean"
	catalog="hibernate" table="t_stus">
	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	<property name="studentName" column="stu_name" type="string" length="20"></property>
	
	
	<many-to-one name="cls" 
	class="org.framestudy.hibernatexmls.beans.ClassBean"
	cascade="all"
	fetch="select"
	lazy="proxy"
	column="fk_class_id"
	></many-to-one>
</class>
</hibernate-mapping>

studentBean的配置

<?xml version="1.0" encoding="UTF-8"?>
<!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="org.framestudy.hibernatexmls.beans.StudentBean"
	catalog="hibernate" table="t_stus">
	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	<property name="studentName" column="stu_name" type="string" length="20"></property>
	
	
	<many-to-one name="cls" 
	class="org.framestudy.hibernatexmls.beans.ClassBean"
	cascade="all"
	fetch="select"
	lazy="proxy"
	column="fk_class_id"
	></many-to-one>
</class>
</hibernate-mapping>

personBean类相关属性

private Long id;
private String personName;
private String password;

private PersonInfoBean personInfo;
private Set<AddressBean> adds;

personBean的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!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="org.framestudy.hibernatexmls.beans.PersonBean" catalog="hibernate" table="t_person">

	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	
	<property name="personName" column="person_name" type="string" length="20"></property>
	<property name="password" column="password" type="string" length="32"></property>


<!-- 拥有外键单向1对1,需要使用many-to-one来完成映射,1对1,同样我们可以看成是1对多 关系的一个特例, 
       唯一的区别是,我们需要将多的一方唯一化,此用unique="true"将1-多关系唯一化。 
	fetch="select" 关联对象在查询时,采用即时加载方式(多条select语句查询) fetch="join" 
        关联对象在查询时,采用预加载查询方式(left join),将会导致懒加载失效 lazy="proxy" 表示将即时加载修改为懒加载,
        关联对象不查询,直接返回动态代理对象,直到程序使用该代理对象时,才去真正的查询数据库,
         通常和fetch="select" 成对出现。 column="fk_info_id" 表示关联外键
	
	cascade 表示级联,与数据库的级联概念是一致的。
	cascade="all" 表示针对“对象”做任何事情,其关联对象,都会跟着同步
	cascade="save-update" 表示针对“对象”做新增或者修改的时候,其关联对象,也会跟着同步 
	cascade="persist" 表示针对“对象”做新增的时候,其关联对象,也会跟着同步 
	cascade="delete" 表示针对“对象”做删除的时候,其关联对象,也会跟着删除
			 -->

	<many-to-one name="personInfo" 
		class="org.framestudy.hibernatexmls.beans.PersonInfoBean" 
		unique="true" 
		fetch="select" 
		lazy="proxy"
		column="fk_info_id"
		cascade="all">
	</many-to-one>
	
	
	<!-- 单向的1对多的配置 -->
	<!--  fetch="select" lazy="true" 针对集合,一定需要配置延迟加载 -->
	<!-- <key column="fk_person_id"></key>  两表之间的关联键-->
	<set name="adds" fetch="select" lazy="true" cascade="all">
		<key column="fk_person_id"></key>
		<one-to-many class="org.framestudy.hibernatexmls.beans.AddressBean"/>
	</set>
	
	
	
	
</class>

</hibernate-mapping>

非注解版一对一

wifeBean.class配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!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="org.framestudy.hibernatexmls.beans.WifeBean" catalog="hibernate" table="t_wife">

	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	
	<property name="wifeName" column="wife_name" type="string" length="20"></property>


	<!-- property-ref="wife" 用于指定某一个属性,与有关联的例外一个属性是谁 -->
	<one-to-one name="hus" 
	class="org.framestudy.hibernatexmls.beans.HusbandBean"
	cascade="all"
	fetch="select"
	lazy="proxy"
	property-ref="wife"
	></one-to-one>
</class>

</hibernate-mapping>

HusbandBean.class配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!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="org.framestudy.hibernatexmls.beans.HusbandBean" catalog="hibernate" table="t_hus">

	<id name="id" column="id" type="long">
		<generator class="identity"></generator>
	</id>
	
	<property name="husName" column="hus_name" type="string" length="20"></property>

	<many-to-one name="wife"
	 class="org.framestudy.hibernatexmls.beans.WifeBean"
	 column="fk_wife_id"
	 unique="true"
	 cascade="all"
	 fetch="select"
	 lazy="proxy"></many-to-one>
</class>

</hibernate-mapping>

但需要对某一个查询语句设置缓存时

Query query = session.createQuery(hql).setCacheable(true);

fetch:关联对象抓取方式,如果放置在left join 与inner join或者full join之后。表示将右侧的关联对象的数据向左侧的主对象进行赋值合并,然后取消掉自己关联对象的显示。如果需要使用关联对象,那么可直接采用:对象.get关联对象()来获取。new map()与fetch不能同时出现,
hql和fetch的区别:

  1. from=select * from
  2. select new 对象(),
  3. select new map(),
  4. left join ...fetch...不能与map同时出现
  5. left join p.关联对象

例子:用于关联表的查询

@Override
public List<?> findClassBeanByStudentName(String stuName) {
	// TODO Auto-generated method stub
	String hql = "From ClassBean as c left join fetch c.stus as s 
                      where s.studentName like CONCAT(?,'%')";
	Query query = session.createQuery(hql);
	query.setString(0, stuName);
	return query.list();
}

fetch和map的区别:

@Override
public List<?> findPersonsByAddress(String address) {
	// TODO Auto-generated method stub
	
	/*fetch 关联对象抓取方式,如果放置在left join 与inner join 或值full join 之后,表示
	 将右侧的关联对象的数据,向左侧的主对象进行赋值合并, 然后取消掉自己关联对象的显示,
	 合并之后,如果需要使用关联对象,那么则可以直接采用:对象.get关联对象()  来获取*/
      // String hql = "From PersonBean as p left join fetch p.personInfo as pf left join fetch p.adds as pa 
                       where pa.address like CONCAT(?,'%')";

	/* new map() 与fetch 不能同时出现,
	*/
     String hql = "select new map (p.personName as personName,pf.infomation as information,pa.address as address)
                      From PersonBean as p left join p.personInfo as pf left join p.adds as pa 
                      where pa.address like CONCAT(?,'%')";
	Query query = session.createQuery(hql);
	query.setString(0, address);
	return query.list();
}

调用一对多方法时的处理方式

@Test
public void testSaveStudentBean() {
	//先查询一个班级
	ClassBean cls = classDaoImpl.getClassBeanById(1l);
	System.out.println(cls.getStus());
	
	//然后创建学生
	StudentBean stu = new StudentBean();
	stu.setStudentName("翠花");
	
	//让学生知道班级(学生拥有关系维护的控制权,所以学生需要知道班级,而班级不需要知道学生)
	stu.setCls(cls);
	studentDaoImpl.saveStudentBean(stu);
}

@Test
public void testSaveClassBean() {
	ClassBean clas = new ClassBean();
	clas.setClassName("J148");
	//班级已经将 关系维护的控制权, 交给学生了,那么此处就不能级联刷新学生了
	classDaoImpl.saveClassBean(clas);
}

调用一对一方法时的处理方式

@Test
public void testSaveHusbandBean() {
	HusbandBean hus = new HusbandBean();
	hus.setHusName("老王");
	
	WifeBean wife = new WifeBean();
	wife.setWifeName("老马");
	
	//让老马知道老王,让老王知道老马
	hus.setWife(wife);
	wife.setHus(hus);
	
	husbandDaoImpl.saveHusbandBean(hus);
	
	
}

注解版hibernate的配置
一对一的配置

丈夫表

package org.framestudy.hibernatexmls.beans;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name="t_hus")
public class HusbandBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = -6779123693334806307L;

@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;

@Column(name="hus_name",length=20)
private String husName;

@OneToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_wife_id")
private WifeBean wife;

public HusbandBean() {
	super();
	// TODO Auto-generated constructor stub
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getHusName() {
	return husName;
}

public void setHusName(String husName) {
	this.husName = husName;
}

public WifeBean getWife() {
	return wife;
}

public void setWife(WifeBean wife) {
	this.wife = wife;
}

@Override
public String toString() {
	return "HusbandBean [id=" + id + ", husName=" + husName + ", wife=" + wife + "]";
}
}

妻子表一方

package org.framestudy.hibernatexmls.beans;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name="t_wife")
public class WifeBean implements Serializable {


/**
 * 
 */
private static final long serialVersionUID = -5135580484824506395L;

@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;

@Column(name="wife_name",length=20)
private String wifeName;

//mappedBy="wife" 替代  xml中 property-ref="wife"
@OneToOne(fetch=FetchType.LAZY,mappedBy="wife")
@Cascade(value= {CascadeType.ALL})
private HusbandBean hus;

public WifeBean() {
	super();
	// TODO Auto-generated constructor stub
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getWifeName() {
	return wifeName;
}

public void setWifeName(String wifeName) {
	this.wifeName = wifeName;
}

public HusbandBean getHus() {
	return hus;
}

public void setHus(HusbandBean hus) {
	this.hus = hus;
}

@Override
public String toString() {
	return "WifeBean [id=" + id + ", wifeName=" + wifeName + "]";
}

}

一对多的配置
学生表(多的一方):

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_stus")
public class StudentBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 5982604360916683581L;
@Id
@Column(name="id")
@GenericGenerator(name="id.strategy", strategy="identity")
@GeneratedValue(generator="id.strategy")
private Long id;

@Column(name="stu_name",length=20)
private String studentName;


@ManyToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_class_id")
private ClassBean cls;

public StudentBean() {
	super();
	// TODO Auto-generated constructor stub
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getStudentName() {
	return studentName;
}

public void setStudentName(String studentName) {
	this.studentName = studentName;
}

public ClassBean getCls() {
	return cls;
}

public void setCls(ClassBean cls) {
	this.cls = cls;
}

@Override
public String toString() {
	return "StudentBean [id=" + id + ", studentName=" + studentName + ", cls=" + cls + "]";
}
}

班级表(少的一方):

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name="t_class")
public class ClassBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 6007243270055543649L;

@Id
@Column(name="id")
@GenericGenerator(name="id.strategy", strategy="identity")
@GeneratedValue(generator="id.strategy")
private Long id;

@Column(name="class_name",length=20)
private String className;

@OneToMany(fetch=FetchType.LAZY,mappedBy="cls")
@Cascade(value= {CascadeType.ALL})
private Set<StudentBean> stus;
public ClassBean() {
	super();
	// TODO Auto-generated constructor stub
}
public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public String getClassName() {
	return className;
}
public void setClassName(String className) {
	this.className = className;
}
public Set<StudentBean> getStus() {
	return stus;
}
public void setStus(Set<StudentBean> stus) {
	this.stus = stus;
}


@Override
public String toString() {
	return "ClassBean [id=" + id + ", className=" + className + "]";
}
}

多对多的配置
选手表一方

package org.framestudy.hibernatexmls.beans;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_players")
public class PlayerBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 2446659919914354468L;

@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="uuid.hex")
@GeneratedValue(generator="hibernate.strategy")
private String id;

@Column(name="player_name",length=20)
private String playerName;


@ManyToMany(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinTable(name="t_player_games",joinColumns= {@JoinColumn(name="fk_player_id")},
inverseJoinColumns= {@JoinColumn(name="fk_games_id")})
private Set<GamesBean> games;
public PlayerBean() {
	super();
	// TODO Auto-generated constructor stub
}
public String getId() {
	return id;
}
public void setId(String id) {
	this.id = id;
}
public String getPlayerName() {
	return playerName;
}
public void setPlayerName(String playerName) {
	this.playerName = playerName;
}
public Set<GamesBean> getGames() {
	return games;
}
public void setGames(Set<GamesBean> games) {
	this.games = games;
}


@Override
public String toString() {
	return "PlayerBean [id=" + id + ", playerName=" + playerName + ", games=" + games + "]";
} 
}

游戏表一方

package org.framestudy.hibernatexmls.beans;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_games")
public class GamesBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 3932895055029411781L;

@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="uuid.hex")
@GeneratedValue(generator="hibernate.strategy")
private String id;

@Column(name="game_name",length=20)
private String gamesName;

//mappedBy="games" 含有交出控制权的意思 
@ManyToMany(fetch=FetchType.LAZY,mappedBy="games")
@Cascade(value= {CascadeType.ALL})
private Set<PlayerBean> players;
public GamesBean() {
	super();
	// TODO Auto-generated constructor stub
}
public String getId() {
	return id;
}
public void setId(String id) {
	this.id = id;
}
public String getGamesName() {
	return gamesName;
}
public void setGamesName(String gamesName) {
	this.gamesName = gamesName;
}
public Set<PlayerBean> getPlayers() {
	return players;
}
public void setPlayers(Set<PlayerBean> players) {
	this.players = players;
}


@Override
public String toString() {
	return "GamesBean [id=" + id + ", gamesName=" + gamesName + "]";
}
}

关于多对多一方的选择测试

@Test
public void testPlayerChoiceGames() {

	PlayerBean player = playerDaoImpl.getPlayerById("402884c86078137b016078137f080000");
	List<?> datas = gameDaoImpl.findAllGames();

	if (player.getGames() == null) {
		Set<GamesBean> games = new HashSet<GamesBean>();
		for (Object obj : datas) {
			GamesBean game = (GamesBean) obj;
			games.add(game);
		}
		player.setGames(games);
	} else {
		for (Object obj : datas) {
			GamesBean game = (GamesBean) obj;
			player.getGames().add(game);
		}
	}

	playerDaoImpl.playerChoiceGames(player);
}

当一个类中即存在类变量和集合时

package org.framestudy.hibernatexmls.beans;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
/**
 * 单向的O2O,O2M
 * @author pu
 *
 */

@Entity
@Table(name="t_person")
public class PersonBean implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 7956578179466276687L;

@Id
@Column(name="id")
@GenericGenerator(name="hibernate.strategy", strategy="identity")
@GeneratedValue(generator="hibernate.strategy")
private Long id;

@Column(name="person_name",length=20)
private String personName;

@Column(length=32)
private String password;

@OneToOne(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_info_id")
private PersonInfoBean personInfo;

@OneToMany(fetch=FetchType.LAZY)
@Cascade(value= {CascadeType.ALL})
@JoinColumn(name="fk_person_id")
private Set<AddressBean> adds;

public PersonBean() {
	super();
	// TODO Auto-generated constructor stub
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getPersonName() {
	return personName;
}

public void setPersonName(String personName) {
	this.personName = personName;
}

public String getPassword() {
	return password;
}

public void setPassword(String password) {
	this.password = password;
}

public PersonInfoBean getPersonInfo() {
	return personInfo;
}

public void setPersonInfo(PersonInfoBean personInfo) {
	this.personInfo = personInfo;
}

public Set<AddressBean> getAdds() {
	return adds;
}

public void setAdds(Set<AddressBean> adds) {
	this.adds = adds;
}

@Override
public String toString() {
	return "PersonBean [id=" + id + ", personName=" + personName + ", password=" + password + ", personInfo="
			+ personInfo + ", adds=" + adds + "]";
}
}

配置文件中配置

<!-- 告知XXX.hbm.xml配置文件 -->
	<mapping class="org.framestudy.hibernatexmls.beans.UserBean" />
相关标签: hibernate java