Entity的OneToMany映射(MySQL数据库)

小伙伴被OneToMany映射折腾的够惨,楞是用不明白。主表ID主键并没有如愿以偿作为附表的外键,并且在保存主entity时还报错,说是附表的外键列不能为空…

我想,Hibernate不可能这么弱,肯定是用得不对。一顿搜索一顿琢磨,在MySQL数据库下,要这么做才行:

  1. 数据库层面,附表,即OneToMany的Many方在外键列上首先创建索引,然后添加外键,如下所示。一个job包含多个case,那么job_info就是主表,job_case就是附表。job_case附表里job_id列是外键,指向job_info主表的id列。
alter table job_case add index (jobId)
alter table job_case add foreign key (jobId) references job_info(id)
  1. 在主表的entity类里,添加List< JobCase >域,并且添加OneToMany注解和JoinColumn注解.
  • 2.1 OneToMany注解,需要注意FetchType,如不注明采用Eager模式,就会走Lazy模式,这时entity类最好加上@Transactional注解,保持session,否则后面用到List<JobCase>会报错,没有transaction manager,无法连接DB查询关联的JobCase数据。
  • 2.2 JoinColumn注解,name属性指的是附表外键列的列名(不是附表entity类的域名,是数据库里附表的外键列列名额)
  • 2.3 JoinColumn注解,referencedColumnName指的是数据库主表作为附表外键的那个列名,同第一步里为附表建外键时references job_info(id)是一个道理
  • 2.4 JoinColumn注解里nullable设为true
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name="jobId", referencedColumnName = "id", nullable = true)
private List<JobCase> caseList = new ArrayList<>();
  1. 在附表entity类的,外键列要设置成insertable = false, nullable = true,注意检查DB表对应列的设置,也是可为空才可以,这个设置非常关键…
@Column(name = "jobId", insertable = false, nullable = true)
private long jobId;

为什么附表的外键列设置成nullable才可以呢,不科学啊,外键一般不应该可以为空的呀…

我想了想,是这样的,一般MySQL数据库里,表的ID列在建表时都设置成了自增的,Hibernate在保存记录到数据库里时,它预先生成好的insert sql(OneToMany映射下,主表一条insert语句,附表0至多条insert语句)里是没办法写id值的,只能是在insert会后DB会给表的ID列写入一个自增值。我大胆猜测,Hibernate肯定是根据自己生成的Insert语句,先insert主表,再insert附表,最后去拿主表的id值,update到附表的外键里去。所以附表的外键列必须是insertable=false, nullable = true…

因吹斯汀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章