<三>重温Hibernate one to many 映射配置

原创 2015年07月09日 13:51:49

多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多

也就是说一对多和多对一的映射策略是一样的,只是站的角度不同


用户表:

CREATE TABLE `tbl_user` 

(`id` INT(32) NOT NULL AUTO_INCREMENT,`user_name` VARCHAR(20) NULL DEFAULT NULL,

`password` VARCHAR(20) NULL DEFAULT NULL,PRIMARY KEY (`id`)

)

银行卡表:

CREATE TABLE `tbl_bank` 

(`id` INT(10) NOT NULL AUTO_INCREMENT,`bank_card` VARCHAR(50) NULL DEFAULT NULL,

`user_id` INT(10) NULL DEFAULT '0',PRIMARY KEY (`id`),

INDEX `FK__tbl_user` (`user_id`),

CONSTRAINT `FK__tbl_user` FOREIGN KEY (`user_id`) REFERENCES `tbl_user` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

)


1.单向一对多:只需在放进行配置

public class Users {

private int id;

private String userName;

private String password;

private Set<Bank> bank=new HashSet<Bank>();

}

<hibernate-mapping>

<class name="wb.wk.review.mapping.onetomany.sigenlMapping.Users" table="tbl_user">

<id name="id" column="id" type="java.lang.Integer">

<generator class="identity"></generator>

</id>

<property name="userName" type="java.lang.String" column="user_name"/>

<property name="password" type="java.lang.String" column="password"/>

<!-- 一对多单向关联 -->

<set name="bank" table="tbl_bank" cascade="all" inverse="false">

<key column="user_id" /><!-- 确定关联的外键列 -->

            <one-to-many class="wb.wk.review.mapping.onetomany.sigenlMapping.Bank"/>

</set>

</class>

</hibernate-mapping>

public class Bank {

private int id;

private String bankCard;

private int userId;//不是users对象

}

<hibernate-mapping>

<class name="wb.wk.review.mapping.onetomany.sigenlMapping.Bank" table="tbl_bank">

<id name="id" column="id" type="java.lang.Integer">

<generator class="identity"></generator>

</id>

<property name="bankCard" type="java.lang.String" column="bank_card"/>

<!-- 一对多单向关联 -->

<!--外键-->

<property name="userId" type="java.lang.Integer" column="user_id"/>

</class>

</hibernate-mapping>

运行出现异常:

org.hibernate.exception.ConstraintViolationException:  could not insert: [wb.wk.review.mapping.onetomany.sigenlMapping.Bank]

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

Cannot add or update a child row: a foreign key constraint fails

 (`ppi`.`tbl_bank`, CONSTRAINT `FK_tbl_bank_tbl_user` FOREIGN KEY (`user_id`) REFERENCES `tbl_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

 

一看就是外键的问题。查了半天,也看了hibernate文档,没有针对外键这一块的解释。但是两张表必须通过外键关联啊。最后删除了外键约束。插入成功。不知道咋回事。

Hibernate: 

    insert  intotbl_user (user_name, password) values(?, ?)

Hibernate: 

    insert  intotbl_bank(bank_card, user_id) values(?, ?)

Hibernate: 

insert  intotbl_bank(bank_card, user_id) values(?, ?)

Hibernate: 

    insert  intotbl_bank(bank_card, user_id) values(?, ?)

 

Hibernate: 

update tbl_bank set  user_id=? where  id=?

Hibernate: 

    update tbl_bank set  user_id=? where  id=?

 

Hibernate: 

    update tbl_bank set  user_id=? where  id=?

总结:另外要注意inverse属性,当时我设置了true,维护段就交给"一"端user了,结果插入时候先插入bank,后插入user,bank获取不到user_id

就出错了。



 

2.双向一对多:

一是关系维护端(owner side),多是关系被维护端(inverse side

需要在关联双方都加以配置,而且需要在一的一方设置inverse=true

 

public class Bank {

private int id;

private String bankCard;

private Users users;

}


Bank xml

<hibernate-mapping>

<class name="wb.wk.review.mapping.onetomany.bean.Bank" table="tbl_bank">

<id name="id" column="id" type="java.lang.Integer">

<generator class="identity"></generator>

</id>

<property name="bankCard" type="java.lang.String" column="bank_card"/>

<many-to-one name="users" class="wb.wk.review.mapping.onetomany.bean.Users" column="user_id"></many-to-one>

</class>

</hibernate-mapping>

 

public class Users {

private int id;

private String userName;

private String password;

private Set<Bank> bank;

}

User xml

<hibernate-mapping>

<class name="wb.wk.review.mapping.onetomany.bean.Users" table="print_user">

<id name="id" column="id" type="java.lang.Integer">

<generator class="identity"></generator>

</id>

<property name="userName" type="java.lang.String" column="user_name"/>

<property name="password" type="java.lang.String" column="password"/>

<set name="bank" table="tbl_bank" cascade="all">

<key column="user_id" /><!-- 确定关联的外键列 -->

            <one-to-many class="wb.wk.review.mapping.onetomany.bean.Bank" />

</set>

</class>

</hibernate-mapping>

测试的main方法:

Session session=null;

Transaction tran=null;

try {

session=HibernateSessionFactory.getSession();

tran=session.beginTransaction();

Users users=new Users();

users.setUserName("lko");

users.setPassword("1213456");

Set<Bank> bakSet=new HashSet<Bank>();

Bank b1=new Bank();

b1.setBankCard("s_001");

b1.setUsers(users);

Bank b2=new Bank();

b2.setBankCard("s_002");

b2.setUsers(users);

Bank b3=new Bank();

b3.setBankCard("s_003");

b3.setUsers(users);

bakSet.add(b1);

bakSet.add(b2);

bakSet.add(b3);

users.setBank(bakSet);

session.save(users);

tran.commit();

catch (HibernateException e) {

tran.rollback();

e.printStackTrace();

}finally{

session.flush();

session.close();

}

出现异常:

null id in wb.wk.review.mapping.onetomany.bean.Users entry (don't flush the Session after an exception occurs)

原因:

这个异常原因很多,这块主要是我没有设置外键(外键约束因为单向一对多的时候报错给在删除了),

设置后插入数据成功。

执行如下sql语句:

Hibernate: 

    insert into tbl_user(user_name, password) values (?, ?)

Hibernate: 

    insert into tbl_bank(bank_card, user_id) values (?, ?)

Hibernate: 

    insert  into tbl_bank (bank_card, user_id) values (?, ?)

Hibernate: 

    insert into tbl_bank (bank_card, user_id) values  (?, ?)

Hibernate: 

    update tbl_bank set user_id=? where  id=?

Hibernate: 

    update tbl_bank set  user_id=?  where id=?

Hibernate: 

Update tbl_bank  set user_id=? Where id=?

 

如果在“一”的一方在加上:inverse="true",如下:

<set name="bank" table="tbl_bank" cascade="all" inverse="true">

<key column="user_id" /><!-- 确定关联的外键列 -->

            <one-to-many class="wb.wk.review.mapping.onetomany.bean.Bank"/>

</set>

运行main方法:

Hibernate: 

    insert into tbl_user(user_name, password) values (?, ?)

Hibernate: 

    insert into tbl_bank(bank_card, user_id) values (?, ?)

Hibernate: 

    insert  into tbl_bank (bank_card, user_id) values (?, ?)

Hibernate: 

insert into tbl_bank (bank_card, user_id) values  (?, ?)

发现update语句没了。

这是因为:在一对多中,如果要""方维护关系,就会在插入或是删除""方时去update""方的每一个与这个""的对象有关系的对象。
而如果让"方面维护关系时就不会有update操作,因为关系就是在多方的对象中的,直指插入或是删除多方对象就行了。
当然这时也要遍历""方的每一个对象显示的操作及关系的变化体现到DB中。不管怎样说,还是让""方维护关系更直观一些。

关于inverse的作用

在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。

我们说inverse设立不当会导致性能低下,其实是说inverse设立不当,会产生多余重复的SQL语句甚至致使JDBC exception的throw。这是我们在建立实体类关系时必须需要关注的地方。一般来说,inverse=true是推荐使用,双向关联中双方都设置 inverse=false的话,必会导致双方都重复更新同一个关系。但是如果双方都设立inverse=true的话,双方都不维护关系的更新,这也是 不行的,好在一对多中的一端:many-to-one默认是inverse=false,避免了这种错误的产生。但是多对多就没有这个默认设置了,所以很 多人经常在多对多的两端都使用inverse=true,结果导致连接表的数据根本没有记录,就是因为他们双分都没有责任维护关系。所以说,双向关联中最 好的设置是一端为inverse=true,一端为inverse=false。一般inverse=false会放在多的一端,那么有人提问了, many-to-many两边都是多的,inverse到底放在哪儿?其实hibernate建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。

 

 

 

正确理解hibernate的inverse! many-to-many

Inverse是hibernate双向关系中的基本概念,当然对于多数实体,我们并不需要双向关联,更多的可能会选择单向关联,况且我们大多数人一般采用一对多关系,而一对多双向关联的另一端:多对一的inve...

使用注解的Hibernate one-to-many映射

One to many映射关系指的是两个实体间一个实体可以和多个实体有关联关系,但是多的这一端只能和一的这一端的一个实例有关系。它是一个1 到 n的关系。例如在任何的公司员工可以注册多个银行账户,一个...

hibernate注解版关联映射Many-to-One/Many-to-Many等&异常处理

链接:http://blog.csdn.net/superdog007/article/details/8534443 属性介绍: 1.多对一: span style="font-size:...
  • xn_28
  • xn_28
  • 2017年03月15日 16:12
  • 1441

Hibernate one-to-many many-to-one 的配置

写东西,总是能发现问题,技术上的漏洞正是在这个时候得到弥补的。 表与表之间的关系有多种。一对多很典型,现配置一下,(teacher表 ,student表 )如下 Model: one : privat...

Many-to-One映射

举例如下: 1.Group.java package edu.study.hibernate; public class Group { private int id; private S...
  • yyywyr
  • yyywyr
  • 2011年08月03日 13:11
  • 17254

many-to-one各属性含义

通过many-to-one 元素,可以定义一种常见的与另一个持久化类的关联。 这种关系模型是多对一关联(实际上是一个对象引用-译注):这个表的一个外键引用目标表的 主键字段。 ...

hibernate中一对多(one-to-many)的实例

hibernate中的一对多,一个用户对应多个频道 频道表: CREATE TABLE `channel` ( `channelId` int(11) NOT NULL auto_incr...

Hibernate one-to-many / many-to-one关系映射

现实世界的1对多(多对1)模型在Hibernate中的映射对应为one-to-many / many-to-one。本文通过举例对此加以说明。并附以详细实现代码。 ...
  • daryl715
  • daryl715
  • 2007年11月15日 15:02
  • 13457

Hibernate 返回排序的one-to-many 集合

问题:    在hibernate配置文件中使用元素来做one-to-many映射,以返回排序的集合。结果会出现一些额外的null元素 解决方法:    使用bag元素做映射,设置order-by属性...

SSH学习五 Hibernate one to many assiciation

一对多关系 one的一方使用Set保存它所对应的many的一方的多个数据。使用set因为数据库记录也是没有重复的,Set当然也是没有重复的。 Hibernate有一个有趣的地方,可以查询得到类,然...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:<三>重温Hibernate one to many 映射配置
举报原因:
原因补充:

(最多只允许输入30个字)