spring data jpa 生成实体表

时间:2021-08-29 16:19:55

1、@DynamicInsert和@DynamicUpdate

这两个注解在一定程度上可以增加与数据库操作相关的速度,可以节省SQL语句的执行时间,提高程序的运行效率。

来看一下@DynamicInsert为false时的sql

spring data jpa 生成实体表

insert into class_room (address, name) values (?, ?)

将@DynamicInsert设为true时

spring data jpa 生成实体表

insert into class_room (name) values (?)

spring data jpa 生成实体表

我实际中指示保存了name,第一个中将address也插入了,第二种只是插入name,看出区别了吧,@DynamicUpdate同理

2、主键生成

     @GeneratedValue(strategy = GenerationType.IDENTITY)  mysql自动增长

     @GeneratedValue(strategy = GenerationType.AUTO) jpa默认的

    详细请看以下2篇博客

    https://blog.csdn.net/u012493207/article/details/50846616

    https://www.cnblogs.com/OnlyCT/p/4375268.html

3、@OneToMany  @ManyToOne  @OneToOne

先说一样下级联(cascade)

CascadeType.PERSIST:级联新增(又称级联保存):对order对象保存时也对items里的对象也会保存。对应EntityManager的presist方法。
CascadeType.MERGE:级联合并(级联更新):若items属性修改了那么order对象保存时同时修改items里的对象。对应EntityManager的merge方法 。
CascadeType.REMOVE:级联删除:对order对象删除也对items里的对象也会删除。对应EntityManager的remove方法。
CascadeType.REFRESH:级联刷新:获取order对象里也同时也重新获取最新的items时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据。

CascadeType.ALL:以上四种都是。

个人觉得级联是单向的,不是双向的,意思就是说,我们在设置两个类的对象之间关系的时候,总是在一方设置的很具体,在另外一方设置一个mappedBy即可,但是如果想要两边都能删除的时候,或者在生成的时候,必须在两边都设置cascade=CascadeType.All才有效果

以学生和班级实现一对多和多对一的实现

spring data jpa 生成实体表

spring data jpa 生成实体表

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests2 {

    @Autowired
    private ClassRoomRepository classRoomRepository;
    @Autowired
    private StudentRepository studentRepository;

    /**
     * 通过学生保存
     */
    @Test
    public void saveStudent(){
        Student student = new Student();
        student.setName("aaa");
        student.setAge(7);
        student.setBirthday(new Date());
        ClassRoom classRoom = classRoomRepository.findByName("教室01");
        student.setClassRoom(classRoom);
        studentRepository.save(student);
    }

    /**
     * 通过班级保存
     */
    @Test
    public void saveClass(){
        ClassRoom classRoom = new ClassRoom();
        Set<Student> set = new HashSet<Student>();
        Student student = new Student();
        student.setName("mmm");
        student.setAge(90);
        student.setBirthday(new Date());
        set.add(student);
        classRoom.setName("class");
        classRoom.setStudentSet(set);
        classRoomRepository.save(classRoom);
    }
}

发现通过学生保存信息是能保存全

spring data jpa 生成实体表

而通过班级保存信息不全,班级id没有保存

spring data jpa 生成实体表

要实现添加班级的同时还可以添加上学生,需要在bean中添加一个方法,也就是变相的通过student添加班级

spring data jpa 生成实体表

@Test
    public void saveClass(){
        ClassRoom classRoom = new ClassRoom();
        Student student = new Student();
        student.setName("hhh");
        student.setAge(78);
        student.setBirthday(new Date());
        classRoom.addStudent(student);
        classRoom.setName("vbvb");
        classRoomRepository.save(classRoom);
    }

spring data jpa 生成实体表

spring data jpa 生成实体表

之前说过级联是单项的,举例说明下,目前上面的bean中只有ClassRoom中配置了CascadeType.ALL

@Test
    public void deleteClass(){
        ClassRoom classRoom = classRoomRepository.findByName("jjjj");
        classRoomRepository.delete(classRoom);
    }

这样是可以删除班级包括学生的(这是从班级入口)

@Test
    public void deleteStudent(){
        Student student = studentRepository.findByName("hhh");
        studentRepository.delete(student);
    }

从学生人入口,发现学生和班级都不会删除,此时需要配置student设置CascadeType.ALL

spring data jpa 生成实体表

这样就都能删除了,此处只是个例子,要是实际业务,肯定不能这么设计,删除一个学生这个班级及这个班级的所有学生都给删除了

如果细心会发现,当student不舍自CascadeType.ALL,并且还是关系的维护方式,调用jpa的delete方法不能删除。

此时要么是使用JPQL强制删除,要是是解除学生与班级的关系,看代码

@Service
public class ClassRoomService {
    @Autowired
    private ClassRoomRepository classRoomRepository;
    @Autowired
    private StudentRepository studentRepository;

    @Transactional
    public void deleteStudent(){
        Student student = studentRepository.findByName("yyy");
        student.getClassRoom().getStudentSet().remove(student);
        studentRepository.delete(student);
    }
}
@Test
    public void deleteStudent(){
        classRoomService.deleteStudent();
    }