一.表与表之间的关系
一对一:如一个丈夫对应一个妻子;
一对多:一个班级对应多个学生(建表时在多的一方建立外键指向一的一方的主键);
多对多:一个课程对应多个学生,一个学生对应多个课程。
二.Hibernate的一对多
以客户和联系人为例
1.新建实体类
package com.lgh.entity;
import java.util.HashSet;
import java.util.Set;
/**
* Created by LGH on 2018/3/10.
*/
public class Customer {
private Integer cId;
private String cName;
private String cSource;
private String cPhone;
//一个客户对应多个联系人
private Set<ContactMan> contactManSet=new HashSet<ContactMan>();
public Set<ContactMan> getContactManSet() {
return contactManSet;
}
public void setContactManSet(Set<ContactMan> contactManSet) {
this.contactManSet = contactManSet;
}
public Integer getcId() {
return cId;
}
public void setcId(Integer cId) {
this.cId = cId;
}
public String getcName() {
return cName;
}
public void setcName(String cName) {
this.cName = cName;
}
public String getcSource() {
return cSource;
}
public void setcSource(String cSource) {
this.cSource = cSource;
}
public String getcPhone() {
return cPhone;
}
public void setcPhone(String cPhone) {
this.cPhone = cPhone;
}
}
package com.lgh.entity;
/**
* Created by LGH on 2018/3/10.
*/
public class ContactMan {
private Integer conId;
private String conName;
private String conGender;
private String conPhone;
//多个联系人对应一个客户
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Integer getConId() {
return conId;
}
public void setConId(Integer conId) {
this.conId = conId;
}
public String getConName() {
return conName;
}
public void setConName(String conName) {
this.conName = conName;
}
public String getConGender() {
return conGender;
}
public void setConGender(String conGender) {
this.conGender = conGender;
}
public String getConPhone() {
return conPhone;
}
public void setConPhone(String conPhone) {
this.conPhone = conPhone;
}
}
2.一对多映射配置
Customer.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lgh.entity">
<class name="Customer" table="customer">
<id name="cId" column="cid">
<generator class="native"/>
</id>
<property name="cName" column="cName"/>
<property name="cPhone" column="cPhoe"/>
<property name="cSource" column="cSource"/>
<set name="contactManSet">
<!--column:外键名称
Hibernate机制:双向维护外键,在一和多的一方都要配置外键
-->
<key column="cid"/>
<!--class:为多的一方的全路径-->
<one-to-many class="ContactMan"/>
</set>
</class>
</hibernate-mapping>
ContactMan.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lgh.entity">
<class name="ContactMan" table="contactMan">
<id name="conId" column="conId">
<generator class="native"/>
</id>
<property name="conName" column="conName"/>
<property name="conPhone" column="conPhone"/>
<property name="conGender" column="conGender"/>
<!--name:一的一方属性名,class:一的一方的全路径,column:外键名称-->
<many-to-one name="customer" class="Customer" column="cid"/>
</class>
</hibernate-mapping>
3.在核心配置文件中引入一对多映射配置文件
<mapping resource="com/lgh/entity/ContactMan.hbm.xml"/>
<mapping resource="com/lgh/entity/Customer.hbm.xml"/>
.一对多的级联操作
1.级联保存
(1)保存一个客户,为这个客户添加多个联系人
需求:添加一个客户,为该客户添加一个联系人
方式一:
Session session=null;
Transaction transaction=null;
try {
session=HibernateUtils.getSession();
transaction=session.beginTransaction();
Customer c = new Customer();
c.setcName("百度");
ContactMan man = new ContactMan();
man.setConName("小李");
man.setConPhone("11111");
c.getContactManSet().add(man);
man.setCustomer(c);
session.save(c);
session.save(man);
transaction.commit();
}
catch (Exception e){
transaction.rollback();
}
finally {
session.close();
}
方式二:在一的一方添加级联操作cascade
<set name="contactManSet" cascade="save-update">
<!--column:外键名称
Hibernate机制:双向维护外键,在一和多的一方都要配置外键
-->
<key column="cid"/>
<!--class:为多的一方的全路径-->
<one-to-many class="ContactMan"/>
</set>
简化代码:
Session session=null;
Transaction transaction=null;
try {
session=HibernateUtils.getSession();
transaction=session.beginTransaction();
Customer c = new Customer();
c.setcName("百度");
ContactMan man = new ContactMan();
man.setConName("小李");
man.setConPhone("11111");
c.getContactManSet().add(man);
session.save(c);
transaction.commit();
}
catch (Exception e){
transaction.rollback();
}
finally {
session.close();
}
2.级联删除
(1)删除一个客户,这个客户下的所有联系人也删除
1.保留之前的级联操作在一的一方加入级联delete
<set name="contactManSet" cascade="save-update,delete">
<!--column:外键名称
Hibernate机制:双向维护外键,在一和多的一方都要配置外键
-->
<key column="cid"/>
<!--class:为多的一方的全路径-->
<one-to-many class="ContactMan"/>
</set>
示例:
Session session=null;
Transaction transaction=null;
try {
session=HibernateUtils.getSession();
transaction=session.beginTransaction();
Customer c = session.get(Customer.class, 4);
session.delete(c);
transaction.commit();
}
catch (Exception e){
transaction.rollback();
}
finally {
session.close();
}
3.关系维护
Session session=null;
Transaction transaction=null;
try {
session=HibernateUtils.getSession();
transaction=session.beginTransaction();
ContactMan contactMan = session.get(ContactMan.class, 1);
Customer customer = session.get(Customer.class, 2);
customer.getContactManSet().add(contactMan);
contactMan.setCustomer(customer);
transaction.commit();
}
catch (Exception e){
transaction.rollback();
}
finally {
session.close();
}
执行sql:
可见update执行了两次,是因为它进行了两次关系维护,Hibernate中默认不放弃关系维护,通过配置在一的一方放弃关系维护,inverse默认值为false,true放弃关系,这样就只更新一次
<set name="contactManSet" cascade="save-update,delete" inverse="true">
<!--column:外键名称
Hibernate机制:双向维护外键,在一和多的一方都要配置外键
-->
<key column="cid"/>
<!--class:为多的一方的全路径-->
<one-to-many class="ContactMan"/>
</set>
三.Hibernate的多对多
以用户和角色为例
1.新建实体类
package com.lgh.entity;
import java.util.HashSet;
import java.util.Set;
/**
* Created by LGH on 2018/3/8.
*/
public class User {
//hibernate要求实体类有一个唯一属性
private String id;
private String userName;
private String password;
//一个用户中有多个角色
private Set<Role> roleSet=new HashSet<Role>();
.....
}
package com.lgh.entity;
import java.util.HashSet;
import java.util.Set;
/**
* Created by LGH on 2018/3/11.
*/
public class Role {
private Integer rId;
private String name;
//一个角色对应多个用户
private Set<User> userSet=new HashSet<User>();
...
}
2.新建配置文件
User.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lgh.entity">
<!--配置表和类映射关系-->
<class name="User" table="tb_user">
<id name="id" column="u_id">
<generator class="native"></generator>
</id>
<property name="userName" column="username"/>
<property name="password" column="password"/>
<!--table:第三张表-->
<set name="roleSet" table="user_role" cascade="save-update,delete">
<!--column:当前表在第三张表中外键-->
<key column="u_id" ></key>
<!--另外一张表在第三张表中的id-->
<many-to-many class="Role" column="r_id"/>
</set>
</class>
</hibernate-mapping>
Role.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lgh.entity">
<class name="Role" table="role">
<id name="rId" column="rId">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<set name="userSet" table="user_role">
<key column="r_id"/>
<many-to-many class="User" column="u_id"/>
</set>
</class>
</hibernate-mapping>
3.在核心配置文件中引入
<mapping resource="com/lgh/entity/User.hbm.xml"/>
<mapping resource="com/lgh/entity/Role.hbm.xml"/>
.添加操作
try {
session=HibernateUtils.getSession();
transaction=session.beginTransaction();
User user1 = new User();
user1.setUserName("李");
User user2 = new User();
user2.setUserName("张");
Role role1 = new Role();
role1.setName("司机");
Role role2 = new Role();
role2.setName("策划");
Role role3 = new Role();
role2.setName("总裁");
user1.getRoleSet().add(role1);
user1.getRoleSet().add(role2);
user2.getRoleSet().add(role3);
session.save(user1);
session.save(user2);
transaction.commit();
}
catch (Exception e){
transaction.rollback();
}
finally {
session.close();
}
在多对多中一般不用级联删除,一般通过维护第三张表
(1)让某个用户拥有某个角色