hibernate注解:多对多单向

本次实验环境:spring boot + spring data jpa + hibernate

本次实验用例:
  班级:
      id
      name
  教室:
      id
      name

一般来说,多对多的关系中,不存在共生的关系。本次试验中,使用班级与教室的关系,大学中,一个班级上不同的课去不同的教室。一个教室可以供多个班级上课。暂且规定班级有课程表标明了上课的教室,但是教室没有课程表,不知道有几个班级会在此上课。

#Grade类:
@Entity
@Table(name="t_n2n_grade")
public class Grade {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
    @JoinTable(name="t_grade_room", joinColumns= {@JoinColumn(name="grade_id")}, inverseJoinColumns= {@JoinColumn(name="room_id")})
    private List<Room> rooms;

    //getter与setter省略
}
#Room类:
@Entity
@Table(name="t_n2n_room")
public class Room {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    //getter与setter省略
}
#生成表

这里写图片描述
这里写图片描述
这里写图片描述


CRUD:
  • 在多对多的关系中,按照实际思维,先有东西,再建立关系。即先创建班级,创建教室,然后关连班级和教室。如果非要在创建班级时就关连一个教室或级联创建教室并关连,也是可以的,cascade可以不写,如果要写只能使用MERGE。
  • 添加room,直接添加,或者添加班级时级联添加教室。
    Room room = new Room();
    room.setName("x7503");
    roomDao.saveAndFlush(room);


    Grade grade = new Grade();
    grade.setName("jsj1341");
    Room room = new Room();
    room.setName("篮球场");
    List<Room> list = new ArrayList<>();
    list.add(room);
    grade.setRooms(list);
    gradeDao.saveAndFlush(grade);
  • 更新room,因为room中不含有grade相关属性,所以可以直接更新,不会影响关系。
    Room findOne = roomDao.findOne(1L);
    findOne.setName("x9210");
    roomDao.saveAndFlush(findOne);
  • 查询room,可以通过id直接查询,也可以查询grade,因为是急加载,会把该班级的所有关连教室都查出来。
    Room findOne = roomDao.findOne(1L);

  • 删除room,按照实际情况,删除room之后grade还是存在的,只是两者之间的关连没有了。
    因为单向的关系,从room出发无法找到中间表,所以直接删除的时候不能连同中间表中的关连关系一起删掉,会报错。
    所以必须先从中间表中删除关系然后再删除room。
    Grade grade = gradeDao.findOne(1L);
    List<Room> rooms = grade.getRooms();
    for(Room temp : rooms) {
    if(temp.getId() == 1) {
    rooms.remove(temp);
    break;
    }
    }
    gradeDao.saveAndFlush(grade);
    roomDao.delete(1L);

  • 添加grade,直接添加即可。
    Grade grade = new Grade();
    grade.setName("jsj1343");
    gradeDao.saveAndFlush(grade);

  • 更新grade,因为grade中包含room的相关属性,所以更新grade自身的属性,这里是name,必须确保rooms中的数据与数据库中的原数据一致,所以先查询后更新。
    Grade findOne = gradeDao.findOne(1L);
    findOne.setName("jsj1342");
    gradeDao.saveAndFlush(findOne);

  • 查询grade,直接查询即可,急加载会把相关room的数据一同查出。
  • 删除grade,这里得注意一定不能设置级联删除,即CascadeType.REMOVE。
    级联删除会把grade,连同中间表和room的对应数据都删掉,首先就不符合逻辑,一个班级毕业删掉了连同教室一起删了,这不正确。正确的状态应该是grade没有了,中间表中的关系没有了,但是教室还在。
    如果设置了级联删除,如果其他班级也要使用这个教室,那么删除不成功会报错。
    如果没有设置,直接删除即可,grade表与中间表中的数据会正确删除,而room表不会改变。
    gradeDao.delete(1L);
  • 设置grade与room的关系,实质就是更新grade中的List<Room>类型的变量,注意的要点与更新grade自身属性时一样,没什么好说的。
  • 删除grade与room的关系,建议直接写sql去中间表中删除。通过在接口的方法上加上注解@Query(“”, nativeQuery = true)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值