在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的相关知识,敬请期待`(*∩_∩*)′!