在hibernate中非常重要的就是映射,在前面的博文中,小编简单的介绍了基本映射,基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用。这个比较简单,但是基础知识还是需要好好掌握的哦,还有一些关联映射,比如user && group,她们之间的关系是一对多,我们知道一个用户只能属于一个组,但是一个组可以包好N多个用户,所以他们之间的关系就是多对一的关系,接着我们来看他们的对象模型以及关系模式。
所谓多对一单向关联映射,就是 多的一端维护关联关系,在“多”的一端加入一个外键,指向“一”的一端。多的一端持有一的一端的引用,即在“多”的一端加外键,指向“一”的一端。ok,接着我们来看User and Group的对象模型以及关系模式模型,首先对象模型:
接着关系模型如下所示:
接着,小编用代码来实现相应的原理,还请小伙伴们多多指教哦。
第一步、建立User和Group两个实体类,并且编写代码,首先是User类,代码如下所示:
package com.bjpowernode.hibernate;
public class User {
private int id;
private String name;
private Group group;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}
接着编写Group的代码,如下所示:
package com.bjpowernode.hibernate;
public class Group {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第二步、我们要从用户看到组,所以要关联,so,需要在User里面添加Group代码,编写映射文件User.hbm.xml 和Group.hbm.xml。首先User.hbm.xml,代码如下所示:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<properties name="name"/>
<many-to-one name="group" column="groupid" cascade="save-update"/>
</class>
</hibernate-mapping>
接着编写Group.hbm.xml,代码如下所示:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Group" table="t_group">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
第三步、编写Hibernate.cfg.xml映射文件里面的内容,代码如下所示:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory >
<!-- MySql数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库名称 -->
<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_many2one</property>
<!-- 数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库的密码 -->
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 显示语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式排版 -->
<!-- <property name="hibernate.format_sql">true</property> -->
<mapping resource="com/bjpowernode/hibernate/User.hbm.xml"/>
<mapping resource="com/bjpowernode/hibernate/Group.hbm.xml"/>
</session-factory>
</hibernate-configuration>
第四步、创建数据库,并且运行ExportDB文件,我们来看一下数据库里面的信息,效果如下所示:
关联映射已经搞定,接下来向里面添加数据,看看关联如何发挥作用。
第五步、建立Many2oneTest,编写第一个方法,如下所示:
package com.bjpowernode.hibernate;
import org.hibernate.Session;
import junit.framework.TestCase;
public class Many2oneTest extends TestCase {
public void testSave1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
Group group = new Group();
group.setName("动力节点");
User user1 = new User();
user1.setName("张三");
user1.setGroup(group);
User user2 = new User();
user2.setName("李四");
user2.setGroup(group);
session.save(user1);
session.save(user2);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
运行这个方法,我们发现,在清理缓存的时候发生错误TransientObjectException,因为Group为Transient状态,没有被session,在数据库中没有匹配的数据,而User为persistent状态,在清理缓存时Hibernate在缓存中无法找到Group,so--Persistent状态的对象不能引用Transistent状态的对象,ok,接着,我们来改进一下相关代码如下所示:
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Group group = new Group();
group.setName("动力节点");
session.save(group);
User user1 = new User();
user1.setName("张三");
user1.setGroup(group);
User user2 = new User();
user2.setName("李四");
user2.setGroup(group);
session.save(user1);
session.save(user2);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
运行,发现现在可以可以正确的保存数据,因为Group和User都是Persistent状态的对象所以在hibernate清理缓存时在session中可以找到关联对象。接着再编写一个方法,介绍一个属性,这个属性叫做级联,级联就是一些连锁性的操作,级联的意思是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作。比如保存某个用户的时候,可以级联把别人保存了。首先,修改User.hbm.xml文件的代码,如下所示:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<properties name="name"/>
<many-to-one name="group" column="groupid" cascade="save-update"/>
</class>
</hibernate-mapping>
方法编写,如下所示:
public void testSave3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Group group = new Group();
group.setName("动力节点");
User user1 = new User();
user1.setName("张三");
user1.setGroup(group);
User user2 = new User();
user2.setName("李四");
user2.setGroup(group);
session.save(user1);
session.save(user2);
//没有抛出TransientObjectException异常
//因为使用了级联特性
//hibernate会首先保存User的关联对象对象Group
//Group和User就都是Persistent状态的对象了
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
执行这个方法,ok,运行,如下所示:
小编寄语:该博文,小编主要简单的介绍了hibernate中的多对一单向关联映射,项目中,多对一关联映射是最常见的映射,但它是Hibernate的关联映射中最简单的一种映射关系。学习就是这样,点点滴滴的积累,下篇博文,小编将继续介绍hibernate的相关知识,敬请期待`(*∩_∩*)′!