spring data jpa 生成实体表

1、@DynamicInsert和@DynamicUpdate

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

来看一下@DynamicInsert为false时的sql

spring data jpa 生成实体表_第1张图片

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

将@DynamicInsert设为true时

spring data jpa 生成实体表_第2张图片

insert into class_room (name) values (?)

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

必须注意DynamicUpdate实现更新必须保证在同一个session中,否则是无效果的。

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 生成实体表_第3张图片

spring data jpa 生成实体表_第4张图片

@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 set = new HashSet();
        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);
    }
}

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

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

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

@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);
    }

之前说过级联是单项的,举例说明下,目前上面的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 生成实体表_第5张图片

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

如果细心会发现,当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();
    }

使用OneToOne时,当第二次执行是,执行的是update操作。比如(A对象已经存储了B对象的关系,此时再次存储A对象和C对象的关系,C对象会更新掉B对象)如果使用的OneToMany则会执行insert操作,及A对象同时关联的了B和C对象。

4、@Formula

@Formula多数情况下用于做统计用途,必须注意的是

1)得用括号括起来,

2)关联表起别名

spring data jpa 生成实体表_第6张图片

打印的sql

select classroom0_.id as id1_0_, classroom0_.address as address2_0_, classroom0_.name as name3_0_, (SELECT count(*) FROM student s WHERE s.class_id = classroom0_.id) as formula0_ from class_room classroom0_ where classroom0_.name=?

5、@DateTimeFormat和@JsonFormat

DateTimeFormat主要是入参,及前台传递的日期为字符串类型,后台接收的为日期类型,此时使用此注解,就行字符串到日期的转化。否则会直接报错。

spring data jpa 生成实体表_第7张图片

在bean中添加注解

spring data jpa 生成实体表_第8张图片

spring data jpa 生成实体表_第9张图片

JsonFormat是用来给前台返回日期使用的,通过此注解返回自己想要的格式

未使用此注解返回的数据

spring data jpa 生成实体表_第10张图片

使用注解后

spring data jpa 生成实体表_第11张图片

spring data jpa 生成实体表_第12张图片

需要注解的事,配置Dto文件,如图中,我返回的studentDto而不是student。需要使用ModelMapper转化

@RestController
public class StudentController {
    @Autowired
    private StudentService studentService;
    private final static ModelMapper modelMapper = new ModelMapper();

    @GetMapping("/student")
    public StudentDto setStudentService() {
        Student student = studentService.testStudent3();
        return modelMapper.map(student,StudentDto.class);
    }
    @PostMapping("/save")
    public void saveStudent(Student student){
        studentService.saveStudent(student);
    }
}

6、联合约束uniqueConstraints

@Table(name="lib_case_Collection",uniqueConstraints = {@UniqueConstraint(columnNames = {"case_id","user_id"})})

spring data jpa 生成实体表_第13张图片

7、复合主键@IdClass

spring data jpa 生成实体表_第14张图片

spring data jpa 生成实体表_第15张图片

8、@PostPersist

@PrePersist @PostPersist @PreRemove @PostRemove @PreUpdate @PostUpdate @PostLoad 。它们标注在某个方法之前,没有任何参数。这些标注下的方法在实体的状态改变前后时进 行调用,相当于拦截器,参考图 13.6 实体状态转换关系图,pre 表示在状态切换前触发, post 则表示在切换后触发。 @PostLoad 事件在下列情况触发: 1. 执行 EntityManager.find( )或 getreference( )方法载入一个实体后; 2. 执行 JPA QL 查询过后; 3. EntityManager.refresh( )方法被调用后。 @PrePersist 和 @PostPersist 事 件 在 实 体 对 象 插 入 到 数 据 库 的 过 程 中 发 生 , @PrePersist 事件在调用 EntityManager.persist( )方法后立刻发生, 级联保存也会发生此事 件,此时的数据还没有真实插入进数据库。@PostPersist 事件在数据已经插入进数据库后 发生。 @PreUpdate 和 @PostUpdate 事件的触发由更新实体引起, @PreUpdate 事件在实 体的状态同步到数据库之前触发,此时的数据还没有真实更新到数据库。@PostUpdate 事件在实体的状态同步到数据库后触发,同步在事务提交时发生。 @PreRemove 和 @PostRemove 事件的触发由删除实体引起,@ PreRemove 事件在实体从数据库删除之前触发,即调用了 EntityManager.remove()方法或者级联删除

以PostPersist为例

保存实体后,立马更新,由于我设置的更新时将排序id等于生成的主键id,所有出现2个22

9、indexes

@Table(name = "em_exam_room_distribution",indexes = {@Index(columnList = "examId,roomId")})

spring data jpa 生成实体表_第16张图片

有喜欢的朋友可以关注下头条号《老徐聊技术》

你可能感兴趣的:(spring-data-jpa)