我的网站:欢迎大家访问
JPA进阶-映射
一对多关系
单向
单向一对多用得比较少(性能差),但是还是需要了解,单向一对多其实就是在主表中添加ManyToOne的注解即可
双向
同时在两个类中添加注解,在使用双向连接的时候,主从表外键名称必须一致
这里设计主表为Department
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "department")
public class Department {
@Id
@GeneratedValue
private Long id;
private String name;
public Department() {
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getList() {
return list;
}
public void setList(List<Employee> list) {
this.list = list;
}
@OneToMany(cascade = CascadeType.ALL,mappedBy = "department",fetch = FetchType.LAZY,orphanRemoval = true)
//@JoinColumn(name = "department_id")
List<Employee> list= new ArrayList<Employee>();
}
从表Employee的设计
package com.ifueen.domian;
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee {
public Employee() {
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
两个表的实体类创建好之后,测试以下,如果没有报错那么就表示成功了
/**
* 测试添加功能是否成功
*
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("库布里奇");
Employee employee1 = new Employee();
employee1.setName("希区柯克");
Department department = new Department();
department.setName("电影");
/* department.getList().add(employee);
department.getList().add(employee1);*/
employee.setDepartment(department);
employee1.setDepartment(department);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
jpa.persist(employee);
jpa.persist(employee1);
transaction.commit();
jpa.close();
}
级联操作
为什么需要将两张表关联起来呢?因为将它们进行关联以后,我们便可以进行级联操作,虽然平时用的可能不是太多
级联添加
进行主表的添加,只需要设置好从表的数据,那么从表也会将数据添加进去
/**
* 级联添加
* 双方都需要建立连接和维护
* 在添加的时候只需要添加主表,从表的数据也会随之添加
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("库布里奇");
Employee employee1 = new Employee();
employee1.setName("希区柯克");
Department department = new Department();
department.setName("电影");
department.getList().add(employee);
department.getList().add(employee1);
employee.setDepartment(department);
employee1.setDepartment(department);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
transaction.commit();
jpa.close();
}
级联删除(慎用!容易遭到整个项目组的毒打)
/**
* 级联删除
*/
@Test
public void test3(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 1L);
System.out.println(department);
jpa.remove(department);
transaction.commit();
jpa.close();
}
/**
* 级联删除,通过主表删除从表相关的数据
*/
@Test
public void test4(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
String hql = "update Employee e set e.department = null";
Query query = jpa.createQuery(hql);
query.executeUpdate();
Department department = jpa.find(Department.class, 2L);
jpa.remove(department);
transaction.commit();
jpa.close();
}
/**
* 直接删除多方,不经过主表,主表不会受到影响
*/
@Test
public void test5(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Employee employee = jpa.find(Employee.class, 5L);
jpa.remove(employee);
transaction.commit();
jpa.close();
}
/**
* 级联删除,使用脏数据更新,通过主表删除从表相对应的数据
*/
@Test
public void test6(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 2L);
//脏数据更新
department.getList().clear();
transaction.commit();
jpa.close();
}
多对多关系
单向多对多
单向的多对多其实用的都挺少的,而且使用单向,建表sql语句的冗余度也挺高的,所以这里不进行总结,如果需要了解,可以自行网上搜索一下
双向多对多
这里实现一个案例,通过案例来协助掌握双向多对多
两个表,user和role,分别对应导演和作品的,使他们之间进行关联起来
User表设计
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "user_id")},inverseJoinColumns = {@JoinColumn(name = "role_id")})
private List<Role> roles = new ArrayList<Role>();
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Role表设计
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue
private Long id;
private String name;
public Role() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "role_id")},inverseJoinColumns = {@JoinColumn(name = "user_id")})
private List<User> users = new ArrayList<User>();
@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
两张表的实体类设计好,现在测试
/**
* 多对多连接,生成表
*/
@Test
public void test(){
EntityManager jpa = JPAUtil.getJpa();
}
表结构就搭建好了
下面就可以写功能进行测试
/**
* 多对多连接,添加
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑泽明");
User user1 = new User();
user1.setName("库布里克");
User user2 = new User();
user2.setName("诺兰");
Role role = new Role();
role.setName("七武士");
Role role1 = new Role();
role1.setName("2001太空漫步");
Role role2 = new Role();
role2.setName("星际穿越");
Role role3 = new Role();
role3.setName("黑暗骑士");
//维护关系
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);
jpa.persist(role);
jpa.persist(role1);
jpa.persist(role2);
jpa.persist(role3);
transaction.commit();
jpa.close();
}
/**
* 查询
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
User user = jpa.find(User.class, 3L);
System.out.println(user);
List<Role> roles = user.getRoles();
roles.forEach(System.out::println);
jpa.close();
}
/**
* 多对多连接,只需要添加一张表
*/
@Test
public void test3(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑泽明");
User user1 = new User();
user1.setName("库布里克");
User user2 = new User();
user2.setName("诺兰");
Role role = new Role();
role.setName("七武士");
Role role1 = new Role();
role1.setName("2001太空漫步");
Role role2 = new Role();
role2.setName("星际穿越");
Role role3 = new Role();
role3.setName("黑暗骑士");
//维护关系
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);
transaction.commit();
jpa.close();
}
/**
* 删除,没有配置级联删除
*
*/
@Test
public void test4(){
EntityManager jpa = JPAUtil.getJpa();
jpa.getTransaction().begin();
User user = jpa.find(User.class, 3L);
jpa.remove(user);
jpa.getTransaction().commit();
jpa.close();
}
注意,在使用除了添加功能的时候,需要在生成组策略中配置为,如果value="create"的话每次查询都会把全部数据删除完,真是血的教训!!