1、Hibernate的一对多的关系的映射
(1)一对多关系:
一个部门对应的是多个的员工,一个员工对应的是一个部门
创建表的原则:需要外键和一个表的主键进行应色号
(2)多对多的关系
学生表和课程表的关系,一个学生对应的是多个课程,一个课程也可以对应的是多个学生,这是就需要一个中间的表。
(3)一对一的关系(平时的开发中很少)
建表的原则:唯一外键的对应(将唯一的外键指向的是一个表的主键),主键对应(两种唯一的主键进行对应)
2、关系的配置(一对多的关系的配置)
(1)一对多的简单的操作
对应为一的一方的实体类
import java.util.HashSet;
import java.util.Set;
/**
* 客户的实体(一的一方的实体,要放的是多的一方的集合)
* @author sunmoumou
*/
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;
/**
* 表示对应的多个的对象
* Hibernate默认使用的是Set的集合
*/
private Set<LinkedMan> linkedMEN = new HashSet<LinkedMan>();
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
public String getCust_mobile() {
return cust_mobile;
}
public void setCust_mobile(String cust_mobile) {
this.cust_mobile = cust_mobile;
}
@Override
public String toString() {
return "Customer{" +
"cust_id=" + cust_id +
", cust_name='" + cust_name + '\'' +
", cust_source='" + cust_source + '\'' +
", cust_industry='" + cust_industry + '\'' +
", cust_level='" + cust_level + '\'' +
", cust_phone='" + cust_phone + '\'' +
", cust_mobile='" + cust_mobile + '\'' +
'}';
}
}
对应为多的一方的实体类
/**
* 联系人的实体
*
* @author sumoumou
*/
public class LinkedMan {
private Long lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
private String lkm_mobile;
private String lkm_email;
private String lkm_qq;
private String lkm_position;
private String lkm_memo;
/**
* 放的是对应的一对方的对象
*/
private Customer customer;
public Long getLkm_id() {
return lkm_id;
}
public void setLkm_id(Long lkm_id) {
this.lkm_id = lkm_id;
}
public String getLkm_name() {
return lkm_name;
}
public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
}
public String getLkm_gender() {
return lkm_gender;
}
public void setLkm_gender(String lkm_gender) {
this.lkm_gender = lkm_gender;
}
public String getLkm_phone() {
return lkm_phone;
}
public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
}
public String getLkm_mobile() {
return lkm_mobile;
}
public void setLkm_mobile(String lkm_mobile) {
this.lkm_mobile = lkm_mobile;
}
public String getLkm_email() {
return lkm_email;
}
public void setLkm_email(String lkm_email) {
this.lkm_email = lkm_email;
}
public String getLkm_qq() {
return lkm_qq;
}
public void setLkm_qq(String lkm_qq) {
this.lkm_qq = lkm_qq;
}
public String getLkm_position() {
return lkm_position;
}
public void setLkm_position(String lkm_position) {
this.lkm_position = lkm_position;
}
public String getLkm_memo() {
return lkm_memo;
}
public void setLkm_memo(String lkm_memo) {
this.lkm_memo = lkm_memo;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
@Override
public String
toString() {
return "LinkedMan{" +
"lkm_id=" + lkm_id +
", lkm_name='" + lkm_name + '\'' +
", lkm_gender='" + lkm_gender + '\'' +
", lkm_phone='" + lkm_phone + '\'' +
", lkm_mobile='" + lkm_mobile + '\'' +
", lkm_email='" + lkm_email + '\'' +
", lkm_qq='" + lkm_qq + '\'' +
", lkm_position='" + lkm_position + '\'' +
", lkm_memo='" + lkm_memo + '\'' +
'}';
}
}
配置文件:
一的一方的配置
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hibernate.domain.Customer" table="cst_customer">
<id name="cust_id" column="cust_id">
<generator class="native"/>
</id>
<property name="cust_name" column="cust_name"/>
<property name="cust_source" column="cust_source"/>
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_phone" column="cust_phone"/>
<property name="cust_mobile" column="cust_mobile"/>
<!--set标签
name:放的是多的一方的集合的属性的名称-->
<set name="linkedManS">
<key>
<!--多的一方的外键的名称-->
<column name="lkm_cust_id"/>
</key>
<!--多的一方类的全路径-->
<one-to-many class="com.hibernate.domain.LinkedMan" />
</set>
</class>
</hibernate-mapping>
多的一方的配置文件
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hibernate.domain.LinkedMan" table="cst_linkman">
<id name="lkm_id" column="lkm_id">
<generator class="native"/>
</id>
<property name="lkm_name"/>
<property name="lkm_gender"/>
<property name="lkm_phone"/>
<property name="lkm_mobile"/>
<property name="lkm_email"/>
<property name="lkm_qq"/>
<property name="lkm_position"/>
<property name="lkm_memo"/>
<!--配置的是多对一的关系
name:一的一方的属性
class:一的一方的类的全路径
column:多的一方的在表中的外键名称
-->
<many-to-one name="customer" column="lkm_cust_id" class="com.hibernate.domain.Customer"/>
</class>
</hibernate-mapping>
执行插入的操作
import com.hibernate.domain.Customer;
import com.hibernate.domain.LinkedMan;
import com.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class HibernateTest {
/**
* 保存两个客户和三个联系人
*/
@Test
public void test1(){
Session session = HibernateUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer1 = new Customer();
customer1.setCust_name("java");
Customer customer2 = new Customer();
customer2.setCust_name("linux");
LinkedMan l1 = new LinkedMan();
l1.setLkm_name("l1");
LinkedMan l2 = new LinkedMan();
l2.setLkm_name("l2");
LinkedMan l3 = new LinkedMan();
l3.setLkm_name("l3");
//设置关系
l1.setCustomer(customer1);
l2.setCustomer(customer1);
l3.setCustomer(customer2);
customer1.getLinkedManS().add(l1);
customer1.getLinkedManS().add(l2);
customer2.getLinkedManS().add(l3);
session.save(customer1);
session.save(customer2);
session.save(l1);
session.save(l2);
session.save(l3);
tx.commit();
}
}
发现的问题:在建立的maven的项目,因为没有将相应的映射的文件放在resources文件夹中,所以在执行的过程中发现xml文件没有编译,所以在pom文件中加入一下的配置就可以解决这个配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
(2)如果在保存的过程中只保存一方时候能成功吗?
回答:是不可以的,因为在只保存一个的对象的过程中,一个持久态的对象关注了一个瞬时态的对象。
(3)一对多的级联
级联:在操作对象的时候会将同时将相关的对象进行连接。
级联的方向性:多到一的方向,一到多的方向。
从一的一方保存的到多的地方
一的一方的配置文件 cascade=save-update
<set name="linkedManS" cascade="save-update">
<key>
<!--多的一方的外键的名称-->
<column name="lkm_cust_id"/>
</key>
<!--多的一方类的全路径-->
<one-to-many class="com.hibernate.domain.LinkedMan" />
</set>
然后进行save()的时候只要save的是Customer的对象就行了。
从多的一方进行配置(cascade的属性为save-update)
<many-to-one name="customer" column="lkm_cust_id" class="com.hibernate.domain.Customer" cascade="save-update"/>
这样就可以在执行保存的操作的时候只保存LinkedMan,然后就可以将相应的Customer的值进行保存。
(4)级联的删除
同样的在上面的cascade的属性上加上相应的delete即可
(5)产生多余的sql语句?
解决的方法:
(1)单项的维护
(2)放弃外键的维护权(一般的选择一的一方进行放弃维护权,在一的一方的位置加上inverse为true)
2、多对多的关系
用户表、中间表、角色表。
(1)创建实体
用户实体
import java.util.HashSet;
import java.util.Set;
/**
* @author kiosk
* 用户表的实体类
*
*/
public class User {
private Long user_id;
private String user_code;
private String user_name;
private String user_password;
private String user_state;
private Set<Role> roles = new HashSet<>();
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Long getUser_id() {
return user_id;
}
public void setUser_id(Long user_id) {
this.user_id = user_id;
}
public String getUser_code() {
return user_code;
}
public void setUser_code(String user_code) {
this.user_code = user_code;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
public String getUser_state() {
return user_state;
}
public void setUser_state(String user_state) {
this.user_state = user_state;
}
}
角色类
import java.util.HashSet;
import java.util.Set;
/**
* @author kiosk
* 角色的实体类
*/
public class Role {
private Long role_id;
private String role_name;
private String role_memo;
private Set<User> users = new HashSet<>();
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public Long getRole_id() {
return role_id;
}
public void setRole_id(Long role_id) {
this.role_id = role_id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_memo() {
return role_memo;
}
public void setRole_memo(String role_memo) {
this.role_memo = role_memo;
}
}
(1)用户的保存
在多对多的关系中的,必须要有一方放弃自己对外键的维护权利。
否则在执行保存的操作的时候会出现如下的错误
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '18-9' for key 'PRIMARY'
一般的情况下是被动方放弃维护的权利 inverse = true;
(2)级联的保存
在相应的文件中配置属性cascade = save-update
(3)级联删除(基本上用不上)
在相应的配置文件中cascade=delete
(4)给用户选择角色、改写、删除角色
举例:
删除
@Test
public void test4(){
Session session = HibernateUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
User user = session.get(User.class,14l);
user.getRoles().clear();
tx.commit();
}