简体   繁体   中英

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

I have three classes: PeelTestFile, DiscreteJob and PeelTestFileJob. This is a similar setup to the User,Group and UserGroup classic problem. I'm trying to delete a PeelTestFileJob. When I do so, it is setting the foreign keys to null. This is a problem because I have the foreign keys set to NOT NULL, which is proper. 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).

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

entity class example to join table A many to many table B (in your case DiscreteJob with PeelTestFile):

in table 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:

@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. and try to delete your inverse = true if you dont need it. inverse: If true, Hibernate will not try to insert or update the properties defined by this join. Default to false.

this is parent table example(like PeelTestFile or DiscreteJob in your case) :

@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):

@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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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