简体   繁体   English

如何在休眠状态下从多对多正确删除联接实例

[英]How do I properly delete a join instance from many-to-many in hibernate

I have three classes: PeelTestFile, DiscreteJob and PeelTestFileJob. 我有三个类:PeelTestFile,DiscreteJob和PeelTestFileJob。 This is a similar setup to the User,Group and UserGroup classic problem. 这是类似于User,Group和UserGroup经典问题的设置。 I'm trying to delete a PeelTestFileJob. 我正在尝试删除PeelTestFileJob。 When I do so, it is setting the foreign keys to null. 当我这样做时,它将外键设置为null。 This is a problem because I have the foreign keys set to NOT NULL, which is proper. 这是一个问题,因为我将外键设置为NOT NULL,这是正确的。 I want it to just remove the one record in the database, and then in Java I want it to remove the instance from the two sets to which it belongs (this is where it seems to be setting the null). 我希望它仅删除数据库中的一条记录,然后在Java中希望它从其所属的两个集合中删除该实例(这似乎是在设置null的位置)。

Below is my code. 下面是我的代码。 What's the proper way to do this? 正确的方法是什么?

public class DiscreteJob
{
  private Set<PeelTestFileJob>            peelTestJobs;

  /**
   * @hibernate.set
   *   inverse="true"
   *   lazy="true"
   *   cascade="all-delete-orphan"
   * @hibernate.collection-key
   *   column="WIP_ENTITY_ID"
   * @hibernate.collection-one-to-many
   *   class="com.icumed.ifactory3.dto.PeelTestFileJob"
   */
  public Set<PeelTestFileJob> getPeelTestJobs()
  {
    return this.peelTestJobs;
  }

  public boolean remove(
    PeelTestFileJob peelTestFileJob)
  {
    return this.peelTestJobs.remove(peelTestFileJob);
  }

  public void setPeelTestJobs(
    Set<PeelTestFileJob> peelTestJobs)
  {
    this.peelTestJobs = peelTestJobs;
  }
}

public class PeelTestFile
{
  private Set<PeelTestFileJob>   peelTestFileJobs;

  /**
   * @hibernate.set 
   *   inverse="true"
   *   lazy="true"
   *   cascade="all-delete-orphan"
   * @hibernate.collection-key
   *   column="PEEL_TEST_FILE_ID" 
   * @hibernate.collection-one-to-many
   *   class="com.icumed.ifactory3.dto.PeelTestFileJob"
   */
  public Set<PeelTestFileJob> getPeelTestFileJobs()
  {
    return this.peelTestFileJobs;
  }

  public boolean remove(
    PeelTestFileJob peelTestFileJob)
  {
    return this.peelTestFileJobs.remove(peelTestFileJob);
  }

  public void setPeelTestFileJobs(
    Set<PeelTestFileJob> jobs)
  {
    this.peelTestFileJobs = jobs;
  }
}

public class PeelTestFileJob
{
  private PeelTestFile      peelTestFile;
  private DiscreteJob       job;
  private User              createdBy;
  private Date              creationDate;

  /**
   * @hibernate.many-to-one
   *   column="PEEL_TEST_FILE_ID"
   *   not-null="true"
   *   outer-join="false"
   */
  public PeelTestFile getPeelTestFile()
  {
    return this.peelTestFile;
  }

  public void setPeelTestFile(
    PeelTestFile file)
  {
    this.peelTestFile = file;
  }

  /**
   * @hibernate.many-to-one
   *   column="WIP_ENTITY_ID"
   *   not-null="true"
   *   outer-join="false"
   */
  public DiscreteJob getJob()
  {
    return this.job;
  }

  public void setJob(
    DiscreteJob job)
  {
    this.job = job;
  }
}

Below is my code that's causing the problem: 以下是导致问题的我的代码:

super.getHibernateTemplate().delete(peelTestFileJob);

if (job.remove(peelTestFileJob)) // setting foreign key to null?
{
  if (peelTestFile.remove(peelTestFileJob)) // setting foreign key to null?
  {
    if (peelTestFile.getPeelTestFileJobs().isEmpty())
    {
      // modify the peel test file here

      getPeelTestFileDAO().update(peelTestFile, bioIdentification);
    }
  }
}

you should have 2 entity class + 1 automatically created table for many to many relationship. 您应该有2个实体类+ 1个自动创建的多对多关系表。 and the reason of why your FK data became null because you use set of your relationship table ( Set<PeelTestFileJob> ) instead of set of DiscreteJob or PeelTestFile. 以及为什么FK数据变为空的原因,是因为您使用关系表的Set<PeelTestFileJob>Set<PeelTestFileJob> )而不是DiscreteJob或PeelTestFile的集合。

entity class example to join table A many to many table B (in your case DiscreteJob with PeelTestFile): 连接表A多对多表B的实体类示例(在您的情况下为带有DiscelteFile的DiscreteJob):

in table A: 在表A中:

@ManyToMany(cascade = CascadeType.REFRESH)
@JoinTable(name="A_JOIN_B",
        joinColumns={@JoinColumn(name="A_ID")},
        inverseJoinColumns={@JoinColumn(name="B_ID")})
private Set<TestTableB> testJoins = new HashSet<TestTableB>();

in table B: 在表B中:

@ManyToMany(mappedBy="testJoins")
private Set<TestTableA> testJoins = new HashSet<TestTableA>();

__ _ __ _ __ _ __ _ __ _ __ _ __ _ ___ EDIT _ __ _ __ _ __ _ __ _ __ I test this and this is work : __ _ __ _ __ _ __ _ __ _ __ _ __ _ _ ____ 编辑 _ __ _ __ _ __ _ __ _ __我测试了这个,这是可行的:

the key is to use @OneToMany(mappedBy="bId", cascade = CascadeType.DETACH) bId is FK in join table entity. 关键是使用@OneToMany(mappedBy="bId", cascade = CascadeType.DETACH) bId在联接表实体中为FK。 and try to delete your inverse = true if you dont need it. 并尝试删除您的inverse = true(如果不需要)。 inverse: If true, Hibernate will not try to insert or update the properties defined by this join. 反向:如果为true,则Hibernate将不会尝试插入或更新此联接定义的属性。 Default to false. 默认为false。

this is parent table example(like PeelTestFile or DiscreteJob in your case) : 这是父表示例(在您的情况下为PeelTestFile或DiscreteJob):

@Entity
@Table(name = "TEST_TABLE_B")
public class TestTableB {

    //constructors here

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "B_ID")
    private Long id;

    @Column(name = "B_NAME")
    private String bName;

    @OneToMany(mappedBy="bId", cascade = CascadeType.DETACH)
    private Set<AJoinB> testJoins = new HashSet<AJoinB>();
    //getters and setters here

this A join B table example (in your case PeelTestFileJob): 这个A联接B表示例(在您的情况下为PeelTestFileJob):

@Entity
@Table(name = "A_JOIN_B")
public class AJoinB {
    //constructors here

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private Long id;

    @Column(name = "C_NAME")
    private String aName;
    //you can add another column here

    @Column(name = "A_ID", nullable = false)
    private Long aId;

    @Column(name = "B_ID", nullable = false)
    private Long bId;
    //getter setters here

when i do this command in java i delete 1 row in A join B table: 当我在Java中执行此命令时,我删除了A连接B表中的1行:

TestTableB b = (TestTableB) this.genericDao.getList("from TestTableB b where b.id = 1",false,null).get(0);
Set<AJoinB> testJoins = b.getTestJoins();
AJoinB ab = (AJoinB) testJoins.toArray()[0];
this.genericDao.remove(ab);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM