一、环境搭建
springDataJpa的基本环境搭建在上篇已经讲到,这里不再赘述。环境配置具体链接如下springDataJpa环境搭建
二、OneToMany
1、实体类
这里我们以一个父亲与儿子的关系为例描述一对多,创建的实体类如下
1.1、Father类
package com.xsl.entity;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
//@Entity注解声明这个是一个对应表的有实体
@Entity
//@Table创建表,指定表名
@Table(name = "father")
public class Father {
//@Id主键
@Id
// @GeneratedValue主键生成策略,这里使用的mysql所以自增
@GeneratedValue(strategy = GenerationType.IDENTITY)
//@Column字段与数据库表列映射
@Column(name = "fid")
Long fid;
@Column(name = "name")
String name;
//一的一方放弃外键的维护权
// @OneToMany(targetEntity = Son.class)
// @JoinColumn(name = "s_fid",referencedColumnName = "fid")
@OneToMany(mappedBy = "father",cascade = CascadeType.ALL)//mappedBy放弃维护权,cascade:设置级联
private Set<Son> sons = new HashSet<>();
//以下为构造器、getter、setter、toString方法
public Set<Son> getSons() {
return sons;
}
public void setSons(Set<Son> sons) {
this.sons = sons;
}
public Father(Long fid ,String name) {
this.fid = fid;
this.name = name;
}
public Father() {
}
public Father(String name) {
this.name = name;
}
public Long getFid() {
return fid;
}
public void setFid(Long fid) {
this.fid = fid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Father{" +
"fid=" + fid +
", name='" + name + '\'' +
'}';
}
}
1.2、Son类
package com.xsl.entity;
import javax.persistence.*;
@Entity
@Table(name = "son")
public class Son {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sid")
private Long sid;
@Column(name = "name")
private String name;
//维护关系,targetEntity指对方的字节码
@ManyToOne(targetEntity = Father.class)
//referencedColumnName指的是依照的主要列的字段名
@JoinColumn(name = "s_fid",referencedColumnName = "fid")
private Father father;
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
public Son(Long sid, String name) {
this.sid = sid;
this.name = name;
}
public Son(String name) {
this.name = name;
}
public Son() {
}
public Long getSid() {
return sid;
}
public void setSid(Long sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Son{" +
"sid=" + sid +
", name='" + name + '\'' +
'}';
}
}
2、DAO层
DAO层定义两个接口,继承JpaRepository<K,T>,JpaSpecificationExecutor<K,T>即可
3、测试
package com.xsl.test;
import com.xsl.dao.FatherDao;
import com.xsl.dao.SonDao;
import com.xsl.entity.Father;
import com.xsl.entity.Son;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ManyTableTest {
@Autowired
private FatherDao fatherDao;
@Autowired
private SonDao sonDao;
/**
* 多表
*/
@Test
//多表要添加事务保证connection是同一个
@Transactional
//不要自动回滚
@Rollback(false)
public void test(){
Father father = new Father("肖生亮");
Son son = new Son("肖生亮的儿子");
son.setFather(father);
fatherDao.save(father);
sonDao.save(son);
}
/**
* 级联添加
*/
@Test
@Transactional
@Rollback(false)
public void testCascadeAdd(){
Father father = new Father("肖生亮");
Son son = new Son("肖生亮的儿子");
son.setFather(father);
father.getSons().add(son);
fatherDao.save(father);
}
@Test
@Transactional
@Rollback(false)
public void testCascadeDelete(){
Father one = fatherDao.findOne(5l);
fatherDao.delete(one);
}
}
二、ManyToMany
1、实体类
这里我们以一个学生与老师的关系为例描述多对多,创建的实体类如下
1.1、Teacher类
package com.xsl.entity;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name="teacher")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
//放弃维护权
// @ManyToMany(targetEntity = Student.class)
//多对多其实是增加一个表来维护两实体的关系
// @JoinTable(
// name = "sys_tea_stu",joinColumns =
// //当前表在中间表中的键,两张表各取一个字段作为联合主键
// {@JoinColumn(name = "sys_tea_id",referencedColumnName = "id")},
// //对方对象在中间表的键
// inverseJoinColumns = {@JoinColumn(name = "sys_stu_id",referencedColumnName = "id")}
// )
@ManyToMany(mappedBy = "teachers")
private Set<Student> students = new HashSet<>();
public Teacher() {
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
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 Teacher(Long id, String name) {
this.id = id;
this.name = name;
}
public Teacher(String name) {
this.name = name;
}
}
1.2、Student类
package com.xsl.entity;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "student")
public class Student {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToMany(targetEntity = Teacher.class,cascade = CascadeType.ALL)
@JoinTable(
name = "sys_tea_stu",joinColumns =
//当前表在中间表中的外键
{@JoinColumn(name = "sys_stu_id",referencedColumnName = "id")},
//对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_tea_id",referencedColumnName = "id")}
)
private Set<Teacher> teachers = new HashSet<>();
public Student() {
}
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}
public Student(String name) {
this.name = name;
}
public Student(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"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;
}
}
2、DAO层
DAO层定义两个接口,继承JpaRepository<K,T>,JpaSpecificationExecutor<K,T>即可
3、测试
package com.xsl.test;
import com.xsl.dao.StudentDao;
import com.xsl.dao.TeacherDao;
import com.xsl.entity.Student;
import com.xsl.entity.Teacher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ManyToManyTest {
@Autowired
private StudentDao studentDao;
@Autowired
private TeacherDao teacherDao;
@Test
@Transactional
@Rollback(false)
public void test(){
Student student = new Student("肖生亮");
Teacher teacher = new Teacher("钱小红");
//如果两方都有维护权,两方都添加,会报异常(主键冲突)
student.getTeachers().add(teacher);
studentDao.save(student);
}
@Test
@Transactional
@Rollback(false)
public void testCascadeDelete(){
//cascade操作会把级联的两个关系和中间表一起删掉,慎用
Student one = studentDao.findOne(4l);
studentDao.delete(one);
}
/**
* 测试对象导航查询
*/
@Test
@Transactional
@Rollback(false)
public void testSelect(){
Student one = studentDao.getOne(3l);
Set<Teacher> teachers = one.getTeachers();
for (Teacher tea :
teachers) {
Set<Student> students = tea.getStudents();
System.out.println(students);
}
}
}