[英]Understanding Hibernate Junction Table
I have two entities with one to many relationships as below.我有两个具有一对多关系的实体,如下所示。 Everything works fine except delete action.
除了删除操作外,一切正常。 On deleting, I was getting ERROR: relation "a_b" does not exist .
删除时,我收到错误:关系“a_b”不存在。 For that, I found the solution here .
为此,我在这里找到了解决方案。
According to an answer, there was an issue with the relationship and hibernate treats relationships as separate uni-directional relationships and it will create the third table a_b and tracks both sides of the relationship independently .根据答案,关系存在问题, hibernate 将关系视为单独的单向关系,它将创建第三个表 a_b 并独立跟踪关系的双方。 To resolve the issue I had added mappedBy = "a" .
为了解决这个问题,我添加了mappingBy = "a" 。
Question is问题是
Why does hibernate fires delete query for table a_b while it does not insert into a_b at the time new record creation?为什么 hibernate 会触发对表 a_b 的删除查询,而在创建新记录时它没有插入到 a_b 中?
Log on insert登录插入
Hibernate: insert into a...
Hibernate: insert into b...
Hibernate: insert into b...
Hibernate: insert into b...
**Why insert into a_b... is not generated/inserted?**
Log on delete登录删除
Hibernate: select a0_.id as id1_11_, from a a0_ where (a0_.id in (?))?
Hibernate: delete from b where a_id in (?)
Hibernate: delete from a_b where (a_id) in (select id from a where id in (?))
**Why delete from a_b if nothing is inserted into a_b**
12:19:50.432 [XNIO-1 task-20] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42P01
12:19:50.433 [XNIO-1 task-20] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: relation "a_b" does not exist
with cause = 'org.hibernate.exception.SQLGrammarException: could not execute statement' and exception = 'could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement'
Entity A实体A
@Entity
@Table(name = "a")
public class A extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@OneToMany
private List<B> b;
.....
}
Entity B实体B
@Entity
@Table(name = "b")
public class B extends AbstractAuditingEntity implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@ManyToOne
private A a;
.....
}
AServiceImpl服务实现
@Override
public int delete(List<Long> ids) {
...
bRepository.deleteWithIds(ids);
aRepository.deleteWithIds(ids);
}
BRepository B存储库
@Transactional
@Modifying
@Query("delete from b x where x.a.id in :ids")
void deleteLogsWithIds(@Param("ids") List<Long> ids);
ARepository存储库
@Modifying
@Transactional
@Query("delete from a x where x.id in :ids")
void deleteJobWithIds(@Param("ids") List<Long> ids);
Current Code当前代码
Entity A实体A
@Entity
@Table(name = "a")
public class A extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@OneToMany(mappedBy = "a")
private List<B> b;
.....
}
Entity B实体B
@Entity
@Table(name = "b")
public class B extends AbstractAuditingEntity implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@ManyToOne
private A a;
.....
}
EDIT: Insert sequence编辑:插入序列
Save Entity A保存实体 A
aRepository.saveAndFlush(a);
Make a call to third party API and based on response set Entity A for saving Entity B调用第三方 API 并根据响应集实体 A 保存实体 B
x.forEach(b-> { b.setA(aRepository.findById(aId).get()); bRepository.save(b); });
There can be many scenarios to consider If you are using a uni-directional oneToMany mapping it will require a join table to save the relationship.Since, a single A entity is associated with multiple B entities and due to its unidirectional nature it does not has a mapping column in B table.可能有很多情况需要考虑如果您使用单向oneToMany 映射,则需要一个连接表来保存关系。因为,单个 A 实体与多个 B 实体相关联,并且由于其单向性质,它没有B表中的一个映射列。
enter code here
@Entity
@Table(name = "A")
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private int id;
private String stateName;
//This is uni-directional since we donot have a corresponding reference to A in B entity
@OneToMany(cascade = CascadeType.ALL)
List<B> bs = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<B> getBs() {
return bs;
}
public void setBs(List<B> bs) {
this.bs = bs;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
}
@Entity
@Table(name="B")
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="ID")
private int id;
private String districtName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDistrictName() {
return districtName;
}
public void setDistrictName(String districtName) {
this.districtName = districtName;
}
}
In the above case its uni-directional oneToMany and it will require a join-table.在上面的例子中,它是单向的 oneToMany,它需要一个连接表。
If you save your entity like this enter code here
如果您像这样保存实体,请
enter code here
A a= new A();
B b=new B();
B b1=new B();
List<B> bs=new ArrayList<>();
bs.add(b);
bs.add(b1);
aRepository.save(a);
This will save the relationship mapping in join table.这将在连接表中保存关系映射。
Case 2 :- Now if you add the following in the B entity class it will create a foreign-key column to A table.案例 2 :- 现在,如果您在 B 实体类中添加以下内容,它将为 A 表创建一个外键列。 This will be again a unidirection ManyToOne mapping.
这将再次是一个单向 ManyToOne 映射。
enter code here
@ManyToOne()
A a;
If you the following如果你以下
enter code here
A a =new A();
B b =new B();
b.setA(a);
B b1=new B();
b1.setA(a);
bRepository.save(b);
bRepository.save(b1);
This will not save the relationship in the join table instead it will use the foreign-key which is present in the table B column named A_ID.这不会将关系保存在连接表中,而是会使用名为 A_ID 的表 B 列中存在的外键。
Case 3 :- Bidirectional oneToMany案例 3 :- 双向 oneToMany
enter code here
@Entity
@Table(name = "A")
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private int id;
private String stateName;
@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
List<B> bs = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<B> getBs() {
return bs;
}
public void setBs(List<B> bs) {
this.bs = bs;
}
public void addB(B b) {
b.setA(this);
bs.add(b);
}
public void removeB(B b) {
b.setA(null);
bs.remove(b);
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
}
@Entity
@Table(name = "B")
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private int id;
private String districtName;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "A_ID")
A a;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public String getDistrictName() {
return districtName;
}
public void setDistrictName(String districtName) {
this.districtName = districtName;
}
}
The above entity mapping is bi-directional oneToMany and doesn't uses the join-table.上面的实体映射是双向的oneToMany,不使用连接表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.