1、@DynamicInsert和@DynamicUpdate
这两个注解在一定程度上可以增加与数据库操作相关的速度,可以节省SQL语句的执行时间,提高程序的运行效率。
来看一下@DynamicInsert为false时的sql
insert into class_room (address, name) values (?, ?)
将@DynamicInsert设为true时
insert into class_room (name) values (?)
我实际中指示保存了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才有效果
以学生和班级实现一对多和多对一的实现
@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); } }
发现通过学生保存信息是能保存全
而通过班级保存信息不全,班级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
这样就都能删除了,此处只是个例子,要是实际业务,肯定不能这么设计,删除一个学生这个班级及这个班级的所有学生都给删除了
如果细心会发现,当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(); }