Hibernate持久层框架学习笔记

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" />
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值