多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多
也就是说一对多和多对一的映射策略是一样的,只是站的角度不同
用户表:
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>
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();
}
如果在“一”的一方在加上: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>
发现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建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。