Hello!
I try to reverse engineer my tables (PostgreSQL) which use composit keys for their PK and FK.
See a simple two tables example:
Code:
CREATE TABLE foo (
id INTEGER NOT NULL,
config INTEGER NOT NULL,
foo_string CHARACTER VARYING(250),
CONSTRAINT foo_pk PRIMARY KEY (id, config)
);
CREATE TABLE bar (
id INTEGER NOT NULL,
config INTEGER NOT NULL,
foo_fid INTEGER NOT NULL,
bar_string CHARACTER VARYING(250),
CONSTRAINT bar_pk PRIMARY KEY (id, config),
CONSTRAINT bar_fk FOREIGN KEY (foo_fid, config) REFERENCES foo (id, config)
);
If I reverse engineer my tables I get the following classes (truncated to only show the important parts):
Code:
@Entity
@Table(name = "foo")
public class Foo implements java.io.Serializable {
private FooId id;
private String fooString;
private Set<Bar> bars = new HashSet<Bar>(0);
[...]
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = "id", nullable = false)),
@AttributeOverride(name = "config", column = @Column(name = "config", nullable = false)) })
public FooId getId() {
return this.id;
}
[...]
@OneToMany(fetch = FetchType.LAZY, mappedBy = "foo")
public Set<Bar> getBars() {
return this.bars;
}
}
@Entity
@Table(name = "bar")
public class Bar implements java.io.Serializable {
private BarId id;
private Foo foo;
private String barString;
[...]
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = "id", nullable = false)),
@AttributeOverride(name = "config", column = @Column(name = "config", nullable = false)) })
public BarId getId() {
return this.id;
}
[...]
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "foo_fid", referencedColumnName = "id", nullable = false, insertable = false, updatable = false),
@JoinColumn(name = "config", referencedColumnName = "config", nullable = false, insertable = false, updatable = false) })
public Foo getFoo() {
return this.foo;
}
[...]
}
So far so good.
You can see that the Bar class is missing the foo_fid column. First I thought hibernate get this infomration out of the getFoo() method because the whole Foo-Object is stored in my Bar class.
But this is not the case.
Given the following test insert:
Code:
int config = 1;
Foo foo = new Foo(new FooId(815, config));
foo.setFooString("This is my foo!");
s.save(foo);
Bar bar = new Bar(new BarId(4711, config), foo);
bar.setBarString("This is my bar!");
s.save(bar);
s.getTransaction().commit();
results in the following error output:
Code:
Hibernate: insert into foo (foo_string, config, id) values (?, ?, ?)
Hibernate: insert into bar (bar_string, config, id) values (?, ?, ?)
2015-07-21 10:38:12,988 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper {} - ERROR: null value in column "foo_fid" violates not-null constraint
As you can see hibernate is not inserting the foo_fid which results in the above error coming from the database itself.
If I manually adjust the Bar class by adding the missing fooFid field:
Code:
@Entity
@Table(name = "bar")
public class Bar implements java.io.Serializable {
private BarId id;
private Foo foo;
private String barString;
private int fooFid;
[...]
@Column(name = "foo_fid", nullable = false)
public int getFooFid() {
return fooFid;
}
public void setFooFid(int fooFid) {
this.fooFid = fooFid;
}
}
and slightly adjust the insert example to the following:
Code:
int config = 1;
Foo foo = new Foo(new FooId(815, config));
foo.setFooString("This is my foo!");
s.save(foo);
Bar bar = new Bar(new BarId(4711, config), foo);
bar.setFooFid(foo.getId().getId());
bar.setBarString("This is my bar!");
s.save(bar);
s.getTransaction().commit();
All is working fine.
I wonder if there is no way to reverse engineer such tables or if I do something terrible wrong here...
Appreciate any input for this.
Thanks
Martin