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的区别:
- from=select * from
- select new 对象(),
- select new map(),
- left join ...fetch...不能与map同时出现
- 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" />