了解休眠连接表 [英] Understanding Hibernate Junction Table

查看:80
本文介绍了了解休眠连接表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个具有一对多关系的实体,如下所示.一切正常,除了删除动作.删除时,出现错误:关系"a_b"不存在.为此,我在在此处找到了解决方案.

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. For that, I found the solution here.

根据一个答案,该关系存在问题,并且 hibernate将关系视为单独的单向关系,它将创建第三个表a_b并独立跟踪关系的两侧.为了解决该问题,我添加了 mappedBy ="a" .

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. To resolve the issue I had added mappedBy = "a".

问题是

为什么在创建新记录时,休眠状态会触发对表a_b的删除查询,而该查询没有插入到a_b中呢?

登录插入

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?**

登录删除

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'

实体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;

    .....

}

实体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);
   }

B存储库

@Transactional
@Modifying
@Query("delete from b x where x.a.id in :ids")
void deleteLogsWithIds(@Param("ids") List<Long> ids);

存储库

@Modifying
@Transactional
@Query("delete from a x where x.id in :ids")
void deleteJobWithIds(@Param("ids") List<Long> ids);


当前代码

实体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;

    .....

}

实体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;

        .....
}


插入序列

  1. 保存实体A

  1. Save Entity A

aRepository.saveAndFlush(a);

基于响应集Entity A调用第三方API 用于保存实体B

Make a call to third party API and based on response set Entity A for saving Entity B

x.forEach(b-> { b.setA(aRepository.findById(aId).get()); bRepository.save(b); });

x.forEach(b-> { b.setA(aRepository.findById(aId).get()); bRepository.save(b); });

推荐答案

可以考虑许多方案 如果您使用的是单向映射,则将需要一个联接表来保存关系.由于单个A实体与多个B实体相关联,并且由于其单向性,它没有B表中的映射列.enter code here

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.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;
    }
}

在上述情况下,它是单向的oneToMany,它将需要一个联接表.

In the above case its uni-directional oneToMany and it will require a join-table.

如果您这样保存实体 enter code here

If you save your entity like this 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.

案例2 :-现在,如果在B实体类中添加以下内容,它将为A表创建一个外键列.这将再次是单向的ManyToOne映射.

Case 2:- Now if you add the following in the B entity class it will create a foreign-key column to A table. This will be again a unidirection ManyToOne mapping.

enter code here


  @ManyToOne()
    A a;

如果您遵循

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

这不会将关系保存在联接表中,而是将使用表B列中名为A_ID的外键.

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.

案例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;
    }
}

以上实体映射是双向的oneToMany,并且不使用联接表.

The above entity mapping is bi-directional oneToMany and doesn't uses the join-table.

这篇关于了解休眠连接表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆