JPA3--双向与级联操作
程序员文章站
2022-05-02 08:18:04
...
JPA3–双向与级联操作
一 、单向一对多
1.1配置
在一方配置onetomany
@Entity
@Table(name="t_productDir")
public class ProductDir {
@Id
@GeneratedValue
private Long id;
private String name;
//配置多方 List/Set
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="dir_id")
@OrderBy("price desc")
private List<Product> products = new ArrayList<>();
多方配置:
@Entity
@Table(name="t_product")
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
1.2保存操作:
不管是先保存一方还是多方,都有额外发送sql ,效率上面比较低,建议使用单向多对一,如果要学习双向 这个也要学习
1.3在使用集合的时候,使用接口 比如List/Set(掌握)
List主要有顺序上面 比如组合就可以使用
Set主要多对多 多对一上面 没有顺序 但是orderby 也可以排序
二、双向多对一或者一对多
2.1配置:
@Entity
public class ProductDir {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy=”dir”)
// @JoinColumn(name="dir_id")
private Set<Product> products = new HashSet<Product>();
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY) // 实现延迟加载
@JoinColumn(name = "dir_id")
private ProductDir dir;
}
2.2保存代码案例:
public void testManytoOne2() throws Exception{
//保存数据
Product product1= new Product();
product1.setName("华硕飞行堡垒");
Product product2 = new Product();
product2.setName("联想拯救者");
ProductDir dir = new ProductDir();
dir.setName("笔记本电脑");
//设置关系
dir.getProducts().add(product1);
dir.getProducts().add(product2);
product1.setDir(dir);
product2.setDir(dir);
//保存
EntityManager entityManager = JpaUtils.getEntityManager();
entityManager.getTransaction().begin();
//双向的
entityManager.persist(dir);
entityManager.persist(product1);
entityManager.persist(product2);
entityManager.getTransaction().commit();
entityManager.close();
2.3级联操作
配置:
级联保存((mappedBy = "dir" 表示将外键的维护交给多方管理,dir表示多方中字段属性名,,cascade = CascadeType.PERSISIT 表示可以使用级联保存,除了PERSISIT,常用的还有ALL ,remove)
@OneToMany(mappedBy = "dir",cascade = CascadeType.PERSISIT)
@Test
public void testCascade() throws Exception{
//保存数据
Product product1= new Product();
product1.setName("被子");
Product product2 = new Product();
product2.setName("枕头");
ProductDir dir = new ProductDir();
dir.setName("床上用品");
//设置关系
dir.getProducts().add(product1);
dir.getProducts().add(product2);
product1.setDir(dir);
product2.setDir(dir);
//保存
EntityManager entityManager = JpaUtils.getEntityManager();
entityManager.getTransaction().begin();
//双向的(保存乙方自动保存另外一方想关的)
entityManager.persist(dir);
entityManager.getTransaction().commit();
entityManager.close();
}
级联删除
@OneToMany(mappedBy = "dir",cascade = CascadeType.REOMOVE)
//级联删除:删除一方,然后级联删除多方
@Test
public void testDelete1() throws Exception{
//删除分类7的时候,把多方也删除
EntityManager entityManager = JpaUtils.getEntityManager();
entityManager.getTransaction().begin();
ProductDir productDir = entityManager.find(ProductDir.class, 1L);
entityManager.remove(productDir);
entityManager.getTransaction().commit();
entityManager.close();
三、单向多对多
3.1配置
用户配置:
@Table(name="t_user")
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name="t_user_role",joinColumns ={@JoinColumn(name="user_id")},inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<Role> roles = new HashSet<>();
角色:
@Entity
@Table(name="t_role")
public class Role {
@Id
@GeneratedValue
private Long id;
private String name;
3.2保存操作
public void testCreat() throws Exception{
JpaUtil.getEntityManager();
// 保存2个用户,保存3个角色(5条)
User user1 = new User();
user1.setName("猪儿虫");
User user2 = new User();
user2.setName("猪八戒");
Role role1 = new Role();
role1.setName("司机");
Role role2 = new Role();
role2.setName("演员");
Role role3 = new Role();
role3.setName("验黄师");
// 保存中间表:建立用户到角色关系user1(role1,role2),user2(role1,role2,role3)(5条)
user1.getRoles().add(role1);
user1.getRoles().add(role2);
user2.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
EntityManager entityManager = JpaUtil.getEntityManager();
entityManager.getTransaction().begin();
//保存用户
entityManager.persist(user1);
entityManager.persist(user2);
// 保存角色
entityManager.persist(role1);
entityManager.persist(role2);
entityManager.persist(role3);
entityManager.getTransaction().commit();
entityManager.close();
}
四、双向的多对多
4.1配置:
//学生配置
@Entity
@Table(name = "t_student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
//级联保存的配置
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="t_student_teacher",joinColumns = {@JoinColumn(name="stu_id")},inverseJoinColumns ={@JoinColumn(name = "t_id")})
private Set<Teacher> tset = new HashSet<>();
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 Set<Teacher> getTset() {
return tset;
}
public void setTset(Set<Teacher> tset) {
this.tset = tset;
}
//老师配置
@Entity
@Table(name="t_teacher")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JoinColumn(name="t_name")
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="t_student_teacher",joinColumns = {@JoinColumn(name="t_id")},inverseJoinColumns ={@JoinColumn(name = "stu_id")})
private Set<Student> cont = new HashSet<>();
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 Set<Student> getCont() {
return cont;
}
public void setCont(Set<Student> cont) {
this.cont = cont;
}
4.2级联操作和其他操作:
//级联保存操作 需要的配置(@manytomany(cascade = CascadeType.PERSIST))PERSIST 表示只能级联保存,可以有all,remove配置
@Test
public void testAdd() throws Exception{
EntityManager entityManager = JpaUtil.getEntityManager();
Student student1 = new Student();
Student student2 = new Student();
Student student3 = new Student();
student1.setName("王大锤");
student2.setName("刘全有");
student3.setName("张全蛋");
Teacher teacher1 = new Teacher();
Teacher teacher2 = new Teacher();
teacher1.setName("孙悟空");
teacher2.setName("邱少华");
student1.getTset().add(teacher1);
student1.getTset().add(teacher2);
student2.getTset().add(teacher2);
student2.getTset().add(teacher1);
student3.getTset().add(teacher1);
entityManager.getTransaction().begin();
entityManager.persist(student1);
entityManager.persist(student2);
entityManager.persist(student3);
entityManager.getTransaction().commit();
}
public void testDelete() throws Exception{
//普通的删除(会删除查找的数据,并且删除Id相关表的关系链接)
EntityManager entityManager = JpaUtil.getEntityManager();
Student student = entityManager.find(Student.class, 1L);
entityManager.getTransaction().begin();
entityManager.remove(student);
entityManager.getTransaction().commit();
}
//删除student2与teacher2的关联
@Test
public void testDelete2() throws Exception{
EntityManager entityManager = JpaUtil.getEntityManager();
Student student2 = entityManager.find(Student.class, 2L);
Teacher teacher = entityManager.find(Teacher.class, 2L);
entityManager.getTransaction().begin();
student2.getTset().remove(teacher);
entityManager.getTransaction().commit();
}
//删除student3的所有teacher相关的关系
@Test
public void testDelete3() throws Exception{
EntityManager entityManager = JpaUtil.getEntityManager();
Student student3 = entityManager.find(Student.class, 3L);
entityManager.getTransaction().begin();
student3.getTset().clear();
entityManager.getTransaction().commit();
}
//级联删除
@Test
public void testJLdelete() throws Exception{
//第一步配置级联删除
EntityManager entityManager = JpaUtil.getEntityManager();
Student student = entityManager.find(Student.class, 1L);
entityManager.getTransaction().begin();
entityManager.remove(student);
entityManager.getTransaction().commit();
}
五、Jpa的优化:
常用:
(1)尽量使用单向多对一去代替单向一对多
如果实在要使用双向的配置,尽量的一方放弃管理
(2)常用多对多的配置,中间表会自动产生,jointable
单向和双向
(3)一对一 看特殊的 多对一 -->基本不用
注意:实在要使用一对一 尽量使用唯一的外键
(4)表字段尽量少,(有缓存),表不要怕多,jpa自动创建好这个关系