I have an entity, that i'd like to join OneToOne with a table with a composite key (Omitting getters/setters):
@Entity
@Table(name = "parent")
public class Parent {
@Id
private String parentId;
@Column(name = "data")
private String data;
@OneToOne
private Child child;
}
And:
@Entity
@IdClass(ChildKey.class)
@Table(name = "child")
public class Child{
@Id
private String parentId;
@Id
private String username;
@Column(name = "data")
private String childData;
}
public class ChildKey implements Serializable {
private String parentId;
private String username;
}
Parent does not have a notion of the 'username' field in the Child entity. I need to pass this in as criteria. In the DB, the primary key of child is on parentId and username.
If I don't specify a JoinColumn, hibernate attempts to map using fields child_username and child_parentId. If I specify only one Joincolumn, I get a broken mapping. If I specify both JoinColumns, I have no column on parent to specify.
How can I map this class and pass in the username as criteria? (it is coming from authentication data) Or how can I do this in a different way if I'm off track.
You might be able to use a Derived Identity.
The Parent
class would remain the same; but you would specify a @OneToOne
mapping back to the child's parent and the Child
and ChildKey
classes would look like this:
@Entity
@IdClass(ChildKey.class)
@Table(name = "child")
public class Child{
@Id
@OneToOne(mappedBy="child")
private Parent parent;
@Id
private String username;
@Column(name = "data")
private String childData;
}
public class ChildKey implements Serializable {
private String parent; // name matches name of the @Id field and type matches type of Parent @Id field
private String username; // name and type match those of the @Id field
}
Derived identity is discussed in JPA 2.1 spec, section 2.4.1.
What I ended up doing was defining a @Filter on the Child class, like so:
@Entity
@IdClass(ChildKey.class)
@Table(name = "child")
@FilterDef(name = "usernameFilter", parameters = {
@ParamDef( name = "username", type="string")
})
public class Child { ... }
On the Parent class, I annotated the collection with a reference to the filter:
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "parentId")
@Filter(name="usernameFilter", condition = "username = :username")
private List<Child> children;
Finally, in my DAO, I parameterized the filter by name like so:
Filter filter = currentSession().enableFilter("usernameFilter");
filter.setParameter("username", user.getUsername());
Doing this resulted in the exact SQL I had in mind, which is an additional clause in the JOIN criteria with a variable:
SELECT
...
FROM
parent this_
LEFT OUTER JOIN
child child_ ON this_.parentId = child_.parentId
AND child_.username = ?
I might not have been clear about what end result I was looking for in my original question. Posting this answer in case it helps someone else.
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.