jpa是完全体对象关系映射的接口规范,
其中实体关系分为
@OneToOne, @OneToMany, @ManyToOne, @ManyToMany等
下面的user实体,使用到了以上的各注解,分别维护了各种关系,构建好实体对象后,直接使用entitymanager进行各种操作即可。
@Entity
@Table(name = "user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private Integer age;
// user和document是一对一的关系, 在user中维护, document不维护
@OneToOne(cascade = CascadeType.ALL) // 级联所有, 对user实体的任何操作都会级联到document数据
@JoinColumn(name = "user_document_id") // 表示在user表中的字段名称
private UserDocument userDocument;
@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(
name = "r_user_cource",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Cource> cource;
@ManyToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.DETACH})
@JoinColumn(name = "school_id")
private School school;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
private List<Phone> phone;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", userDocument=" + userDocument +
// ", cource=" + cource +
", school=" + school +
", phone=" + phone +
'}';
}
}
这里重点介绍下manytomany的测试例子;
与user是多对多关系的是Course实体,
@Data
@Entity
@Table(name = "course")
public class Cource {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// 课程名称
private String name;
// 多少学时
private Integer num;
// 实体映射关系
@ManyToMany(cascade = CascadeType.PERSIST)// 级联级别
@JoinTable(
name = "r_user_cource", // 关联中间表
joinColumns = @JoinColumn(name = "course_id"), // 关联字段
inverseJoinColumns = @JoinColumn(name = "user_id") // 级联字段
)
private List<User> users;
@Override
public String toString() {
return "Cource{" +
"id=" + id +
", name='" + name + '\'' +
", num=" + num +
// ", users=" + users +
'}';
}
}
可以看到双方都维护了@ManyToMany 引用约束,此时通过两边的实体都可与进行级联操作,
测试类
这些测试方法,给出了增删该查的实例操作;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ManyToManyTest {
@Autowired
private EntityManager entityManager;
@Test
@Transactional
@Rollback(false)
public void contextLoads() {
User user = new User();
user.setName("李明");
user.setAge(11);
User user2 = new User();
user2.setName("王华");
user2.setAge(14);
Cource course = new Cource();
course.setName("数学");
course.setNum(64);
Cource course2 = new Cource();
course2.setName("语文");
course2.setNum(64);
Cource course3 = new Cource();
course3.setName("英语");
course3.setNum(64);
List<Cource> list1 = new ArrayList<>();
list1.add(course);
list1.add(course2);
list1.add(course3);
List<Cource> list2 = new ArrayList<>();
list2.add(course);
list2.add(course2);
user.setCource(list1);
user2.setCource(list2);
entityManager.persist(user);
entityManager.persist(user2);
}
@Test
@Transactional
@Rollback(false)
public void save() {
User user = new User();
user.setName("李明");
user.setAge(11);
User user2 = new User();
user2.setName("王华");
user2.setAge(14);
Cource course = new Cource();
course.setName("数学");
course.setNum(64);
Cource course2 = new Cource();
course2.setName("语文");
course2.setNum(64);
Cource course3 = new Cource();
course3.setName("英语");
course3.setNum(64);
List<User> list1 = new ArrayList<>();
list1.add(user);
list1.add(user2);
List<User> list2 = new ArrayList<>();
list2.add(user);
course.setUsers(list1);
course2.setUsers(list2);
course3.setUsers(list1);
entityManager.persist(course);
entityManager.persist(course2);
entityManager.persist(course3);
}
@Test
@Transactional
@Rollback(false)
public void update(){
User user = entityManager.find(User.class,9L);
user.getSchool().setName("haha");
entityManager.merge(user);
}
@Test
@Transactional
@Rollback(false)
public void findcource(){
Cource cource = entityManager.find(Cource.class, 25L);
System.out.println(cource);
}
@Test
@Transactional
@Rollback(false)
public void delete(){
User user = entityManager.find(User.class,15L);
entityManager.remove(user);
}
}
需要注意的是,在多对多关系中, 如果设置了cascade = CascadeType.ALL 或者包含 CascadeType.REMOVE 则在级联删除时,除了删除中间表,还会删除多对多关系中对应的另一方的实体表的数据,一般情况下这是不符合业务逻辑的。其实多对多关系中,不要设置级联删除即可,这是通过entitymanger删除对象会将中间表删除。
项目地址 git@github.com:Christain1993/jpatest.git