Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Problem with persist order in 3 table scenario including inheritance and OneToMany relationship
Problem with persist order in 3 table scenario including inheritance and OneToMany relationship [message #813913] Mon, 05 March 2012 16:01 Go to previous message
Michael Gruebsch is currently offline Michael Gruebsch
Messages: 8
Registered: March 2012
Junior Member
Hi,

I have a 3-table-scenario running on Postgres 9.1 with EclipseLink 2.3.1

Table A/class A is the super-table/-class of table B/class B; inheritance strategy is joined.

The 3rd table is H which has a foreign key to B. In Java it is a OneToMany-Relationship from B to H (cascade=ALL).

If I create a new instance of Class B and set a relation from B to a new instance of H, then I get errors when EclipseLink persists the entities. EclipseLinks save the table data in that order:


A (because B inherits from A; primary key is defined there)
H
B

That is: H is saved before B. However, because table H references B by a foreign key this is the wrong order: when H is saved there is no corresponding row in B. The transaction fails:
Could not create the view: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.1.v20110908-r10021): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: insert or update on table "h" violates foreign key constraint "fk_h_b"
  Detail: Key (h_id)=(3) is not present in table "b".
Error Code: 0
Call: INSERT INTO H (X, h_id) VALUES (?, ?)
	bind => [1, 3]
Query: InsertObjectQuery(de.viate.gwai.core.dao.entity.test.H@b398da)


Is there any way to influence the persist order? Does anybody have a clue how to get this stuff working?

Below you find the sources. Thank you

Michael


SQL
===
CREATE SEQUENCE A_A_ID_seq INCREMENT 1 START 1;

CREATE TABLE A ( 
  A_ID integer DEFAULT nextval(('A_A_ID_seq'::text)::regclass) NOT NULL,
  TYP char(1) NOT NULL
);

CREATE TABLE B ( 
  B_ID integer NOT NULL
);


CREATE TABLE H ( 
  H_ID integer NOT NULL,
  X integer not null
);

ALTER TABLE A ADD CONSTRAINT PK_A PRIMARY KEY (A_ID);

ALTER TABLE B ADD CONSTRAINT PK_B PRIMARY KEY (B_ID);

ALTER TABLE H ADD CONSTRAINT PK_H PRIMARY KEY (H_ID, X);

ALTER TABLE B ADD CONSTRAINT FK_B_A FOREIGN KEY (B_ID) REFERENCES A (A_ID);

ALTER TABLE H ADD CONSTRAINT FK_H_B FOREIGN KEY (H_ID) REFERENCES B (B_ID);


JAVA
====

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "typ")
public class A implements Serializable
{
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "a_id")
  private Integer aId;

  public A()
  {
  }

  public Integer getAId()
  {
    return this.aId;
  }

  public void setAId(Integer aId)
  {
    this.aId = aId;
  }
}

@Entity
@DiscriminatorValue("B")
@PrimaryKeyJoinColumn(name = "b_id")
public class B extends A implements Serializable
{
  private static final long serialVersionUID = 1L;

  // bi-directional many-to-one association to H
  @OneToMany(mappedBy = "b", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<H> hs;

  public B()
  {
  }

  public Set<H> getHs()
  {
    return this.hs;
  }

  public void setHs(Set<H> hs)
  {
    this.hs = hs;
  }

}

@Entity
public class H implements Serializable
{
  private static final long serialVersionUID = 1L;

  @EmbeddedId
  private HPK id;

  // bi-directional many-to-one association to B
  @ManyToOne(optional = false)
  @JoinColumn(name = "h_id")
  private B b;

  public H()
  {
  }

  public HPK getId()
  {
    return this.id;
  }

  public void setId(HPK id)
  {
    this.id = id;
  }

  public B getB()
  {
    return this.b;
  }

  public void setB(B b)
  {
    this.b = b;
  }

}
@Embeddable
public class HPK implements Serializable
{
  // default serial version id, required for serializable classes.
  private static final long serialVersionUID = 1L;

  @Column(name = "h_id", insertable=false, updatable=false, nullable=false)
  private Integer hId;

  private Integer x;

  public HPK()
  {
  }

  public Integer getHId()
  {
    return this.hId;
  }

  public void setHId(Integer hId)
  {
    this.hId = hId;
  }

  public Integer getX()
  {
    return this.x;
  }

  public void setX(Integer x)
  {
    this.x = x;
  }

  @Override
  public boolean equals(Object other)
  {
    if (this == other)
    {
      return true;
    }
    if (!(other instanceof HPK))
    {
      return false;
    }
    HPK castOther = (HPK) other;
    return this.hId.equals(castOther.hId) && this.x.equals(castOther.x);

  }

  @Override
  public int hashCode()
  {
    final int prime = 31;
    int hash = 17;
    hash = hash * prime + this.hId.hashCode();
    hash = hash * prime + this.x.hashCode();

    return hash;
  }
}

...

      EntityManager e = ...;
      
      B b = new B();
      H h = new H();
      HPK hpk = new HPK();
      hpk.setX(1);
      h.setId(hpk);
      h.setB(b);
      Set<H> hs = new HashSet<H>();
      hs.add(h);
      b.setHs(hs);
      
      e.persist(b);



 
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic:MOXy - specify element form in external bindings
Next Topic:EclipseLink 2 on Tomcat
Goto Forum:
  


Current Time: Tue May 21 02:47:52 EDT 2013

Powered by FUDForum. Page generated in 0.05095 seconds