I have two classes Foo
and Bar
. The tables in the database look like this:
|Foo|
|id : INT (PK) | bar_id : INT (PK, FK) |
|Bar|
|id : INT (PK) |
Normally I would map it like this:
@Entity
public class Bar
{
@Id
@Column(name = "id")
private int id;
@OneToMany
private Set<Foo> foo;
}
@Entity
public class Foo
{
@EmbeddedId
private FooPK key;
@MapsId("barId")
@ManyToOne
@JoinColumn(name = "bar_id", referencedColumnName = "id")
private Bar bar;
}
@Embeddable
public class FooPK
{
@Column(name = "id")
private int id;
@Column(name = "bar_id")
private int barId;
}
However the id's in FooPK
are loosely mapped and need to be connected manually. I would prefer a solution that maps using Objects in stead of loose ids.
I tried the following but (of course) it didn't work, but I think it gives an idea of what I would like to achieve:
@Entity
public class Bar
{
@Id
@Column(name = "id")
private int id;
@OneToMany
private Set<Foo> foo;
}
@Entity
public class Foo
{
@EmbeddedId
private FooPK key;
@MapsId("barId")
@ManyToOne
@JoinColumn(name = "bar_id", referencedColumnName = "id")
@Access(AccessType.FIELD)
private Bar getBar()
{
return key.getBar();
}
}
@Embeddable
public class FooPK
{
@Column(name = "id")
private int id;
@Transient
private Bar bar;
//....
@Column(name = "bar_id")
@Access(AccessType.PROPERTY)
private int getBarId
{
return bar.getId();
}
}
Another problem with the latter solution is that the getBarId()
method in FooPK
needs to have a setBarId(Int)
method. Setting the Object using the ID can be done by accessing the data access layer, however this (in my opinion) violates the separation of business/domain/data layers.
So what to do? Go with the first solution and keep the ids in sync manually or is there another (best) practice?