Problem with persist order in 3 table scenario including inheritance and OneToMany relationship [message #813913] |
Mon, 05 March 2012 21:01 |
Michael Gruebsch Messages: 16 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);
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03245 seconds