Can I use #EmbeddedId in case more than 3 relations with composite key ?
relation
parent -> child -> grandchild -> great-grandchild
parent
#Entity
#Table(name="mig_club_info")
public class MigGolfClub {
#Id #Column(name = "club_id")
private String club_id;
}
child
#Embeddable
public class MigCourseId implements Serializable{
private String club_id;
private String course_id;
}
#Entity
#Table(name="mig_course_info")
public class MigCourse {
#EmbeddedId
private MigCourseId migCourseId;
#MapsId("club_id")
#ManyToOne
#JoinColumn(name = "club_id")
private MigGolfClub migGolfClub;
}
grandchild
#Embeddable
public class MigHoleId implements Serializable{
private MigCourseId migCourseId;
private int hole_num;
}
#Entity
#Table(name="mig_hole_info")
public class MigHole {
#EmbeddedId
private MigHoleId migHoleId;
#MapsId("migCourseId")
#ManyToOne
#JoinColumns( {
#JoinColumn(name="club_id"),
#JoinColumn(name="course_id")
})
private MigCourse migCourse;
}
great-grandchild
#Embeddable
public class MigTeeId implements Serializable{
private MigHoleId migHoleId;
private String t_name;
}
#Entity
#Table(name="mig_tee_info")
public class MigTee {
#EmbeddedId
private MigTeeId migTeeId;
#MapsId("migHoleId")
#ManyToOne
#JoinColumns( {
#JoinColumn(name="club_id"),
#JoinColumn(name="course_id"),
#JoinColumn(name="hole_num")
})
private MigHole migHole;
}
I tested and got a error message
nested exception is org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a #MapsId: xxx.xxx.xxx.MigHole"
I succeeded with grandchild (2-relations) , but I failed with greate-grandchild (3-relations)
Can't I use #EmbeddedId in case more than 3 relations with composite key?? --;;
Related
I'm currently developing my project under Spring with JPA.
First off, here is my database schema for the background information
So, I'm undergoing difficulties when I try to use history_id of HISTORY as the primary key of TAG. It gives me ...Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: This class [class com.wrapsody.demo.HistoryTag] does not define an IdClass error.
So I added #IdClass(HistoryTag.HistoryTagAssignId.class) in my HistoryTag.java
#NoArgsConstructor(access = AccessLevel.PROTECTED) #Data #Entity
#IdClass(HistoryTag.HistoryTagAssignId.class)
public class HistoryTag implements Serializable {
#Id
#ManyToOne
private History history;
#Column
private String tagName;
#Builder
public HistoryTag(String tagName) {
this.tagName = tagName;
}
#NoArgsConstructor
public static class HistoryTagAssignId implements Serializable {
private History history;
public HistoryTagAssignId(History history) {
this.history = history;
}
}
}
For the reference, this is History.java
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#Data
#Entity
public class History {
#Id
#GeneratedValue
private Long historyId;
#Column
private String historyMaterName;
#Column
private String historyFreeSetName;
History(String historyMaterName, String historyFreeSetName) {
this.historyMaterName = historyMaterName;
this.historyFreeSetName = historyFreeSetName;
}
}
Any guidance towards solving this error msg is appreciated.
Thanks!
For tag table you dont need entity class. Its duable in History entity with:
#ElementCollection
#CollectionTable(
name="TAG",
joinColumns=#JoinColumn(name="HISTORY_ID")
)
#Column(name="TAG_NAME")
List<String> tags;
https://en.wikibooks.org/wiki/Java_Persistence/ElementCollection#Basic_Collections
I'm having trouble getting my head arround this.
How can I create an one-to-one bidirectional mapping between Organisation and OrganisationAddress? This is what I've tried so far:
I got two tables:
**ORGANISATION**
ORGNO <pk>
BANKNO <pk>
**ORGANISATION_ADDRESS**
ORGNO <pk, fk>
BANKNO <pk, fk>
A Java composite key class for each table:
#Embeddable
public class OrganisationPK implements Serializable {
#Column(name="ORGNO", length=9)
private String orgno;
#Column(name="BANKNO", length=4)
private String bankno;
... getters/setters ...
}
and
#Embeddable
public class OrganisationAddressPK implements Serializable {
#Column(name="ORGNO", length=9)
private String orgno;
#Column(name="BANKNO", length=4)
private String bankno;
... getters/setters ...
}
This is the Java classes for Organisation and OrganisationAddress:
#Entity
#Table(name="ORGANISATION")
public class Organisation implements Serializable{
#Id
private OrganisationPK comp_id;
/** bi-directional one-to-one association to OrganisationAddress */
#OneToOne(mappedBy = "organisation", cascade = CascadeType.ALL)
private OrganisationAddress organisationAddress;
}
and
#Entity
#Table(name="ORGANISATION_ADDRESS")
public class OrganisationAddress implements Serializable {
#Id
#AttributeOverrides({
#AttributeOverride(name = "orgno", column=#Column(name="ORGNO")),
#AttributeOverride(name = "bankno", column=#Column(name="BANKNO"))
})
private OrganisationAddressPK comp_id;
/** bi-directional one-to-one association to Organisation */
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumns({
#PrimaryKeyJoinColumn(name = "ORGNO", referencedColumnName = "ORGNO"),
#PrimaryKeyJoinColumn(name = "BANKNO", referencedColumnName = "BANKNO")
})
private Organisation organisation;
When I run the tests, it gives me this error:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class org.hibernate.OrganisationAddress.
Expected: class org.hibernate.OrganisationAddressPK, got class org.hibernate.OrganisationPK
From this call:
private void deleteOrganisation(Organisation organisation){
Organisation hibOrganisation = (Organisation) getCurrentSession().get(
Organisation.class, new OrganisationPK(
organisation.getOrgNo(), BANKNO.getValue()));
...
How to use IdClass in multiple inheritance entity composite key case ?
#IdClass(IdClassEntity1.class)
class Entity1 {
private long e1pk1;
private long e1pk2;
}
#IdClass(IdClassEntity2.class)
class Entity2 extends Entity1 {
private long e2pk1;
private long e2pk2;
}
class Entity3 extends Entity2 {
private long e3pk1;
private long e3pk2;
}
what should be IdClassEntity2 :
class IdClassEntity2 {
private long e1pk1;
private long e1pk2;
private long e2pk1;
private long e2pk2;
}
or
class IdClassEntity2 {
private IdClassEntity1 idClassEntity1;
private long e2pk1;
private long e2pk2;
}
You can use a #MappedSuperClass or #Entity to declare the #IdClass. The pk is propagated via inheritance.
For example, using #MappedSuperClass, you can do the following:
#MappedSuperClass
#IdClass(IdClassEntity1.class)
public class Entity1 {
#Id private long e1pk;
#Id private long e1pk;
...
#Entity
public class Entity2 extends Entity1 {
...
Using #Entity, follow the same paradigm
I am new to hibernate and having a tough time trying to wrap my head around setting up Joined inheritance with composite Primary Key. With my current setup, I get a:
JDBCException: could not insert: LandHolidayPackage
I am essentially looking for two things:
Are the inheritance annotations in place ?
Is the composite PK setup properly ?
DB Design:
Reference
Here are my classes and the annotations involved:
#Entity
#Table(name = "HOLIDAYPACKAGE")
public final class HolidayPackage {
private Integer idPackage;
private String name;
private Set<HolidayPackageVariant> holidayPackageVariants = new HashSet<HolidayPackageVariant>(0);
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "IDHOLIDAYPACKAGE", nullable = false)
public Integer getIdPackage() {
return idPackage;
}
#OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.ALL}, mappedBy = "holidayPackage")
public Set<HolidayPackageVariant> getHolidayPackageVariants() {
return holidayPackageVariants;
}
// ommitted other part of the code
}
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#Table(name="HOLIDAYPACKAGEVARIANT")
public abstract class HolidayPackageVariant {
private Integer idHolidayPackageVariant;
private HolidayPackage holidayPackage;
private String typeHolidayPackage;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="IDHOLIDAYPACKAGEVARIANT", nullable=false)
public Integer getIdHolidayPackageVariant() {
return idHolidayPackageVariant;
}
#ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="IDHOLIDAYPACKAGE", nullable=false)
public HolidayPackage getHolidayPackage() {
return holidayPackage;
}
#Column(name="TYPEHOLIDAYPACKAGE", nullable=true)
public String getTypeHolidayPackage() {
return typeHolidayPackage;
}
// ommitted setters, equals hashCode
}
#Entity
#Table(name="LANDHOLIDAYPACKAGEVARIANT")
public final class LandHolidayPackageVariant extends HolidayPackageVariant{
private static final String LAND = "LAND";
protected LandHolidayPackageVariant() {}
public LandHolidayPackageVariant(HolidayPackage holidayPackage) {
super(holidayPackage, LAND);
}
}
#Entity
#Table(name="FLIGHTHOLIDAYPACKAGEVARIANT")
public final class FlightHolidayPackageVariant extends HolidayPackageVariant{
private static final String FLIGHT = "FLIGHT";
private Destination originCity;
protected FlightHolidayPackageVariant(){}
public FlightHolidayPackageVariant(HolidayPackage holidayPackage,
Destination originCity) {
super(holidayPackage, FLIGHT);
setOriginCity(originCity);
}
#ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="IDDESTINATION", nullable=false)
public Destination getOriginCity() {
return originCity;
}
// ommited other setters etc functions
}
You annotated the properties in stead of the fields. JPA by default tries to access the fields. If you want JPA to use the fields you have to annotate the class with #AccessType(AccessType.Field).
I am trying to do mapping in JPA.
#Entity
public class Auction {
#Id
private Integer auctionId;
#OneToMany(mappedBy="auctionId")
#MapKey(name="auctionParamId")
private Map<AuctionParam, AuctionParamValue> values;
}
#Entity
public class AuctionParam {
#Id
private Integer auctionParamId;
private String description;
}
#Entity
public class AuctionParamValue {
#EmbeddedId
private AuctionParamValuePK pk;
private String value;
}
#Embeddable
public class AuctionParamValuePK {
#ManyToOne
#JoinColumn(name="auctionId")
private Auction auction;
#ManyToOne
#JoinColumn(name="auctionParamId")
private AuctionParam auctionParam;
}
Showing an error:-
.Error-Details:-Exception Description:
Entity [class
com.eaportal.domain.AuctionParamValue]
uses [class
com.eaportal.domain.AuctionParamValuePK]
as embedded id class
whose access-type
has been determined as [FIELD].
But
[class
com.eaportal.domain.AuctionParamValuePK]
does not define any [FIELD]. It is
likely that you have not provided
sufficient metadata in your id class
[class
com.eaportal.domain.AuctionParamValuePK].
If you come up with a solution please let me know.
Thanks in Advance
Tushar
You cannot use an EmbeddedId with relationships. Use an IdClass.
#Entity
#IdClass(AuctionParamValuePK.class)
public class AuctionParamValue {
#Id
#ManyToOne
#JoinColumn(name="auctionId")
private Auction auction;
#Id
#ManyToOne
#JoinColumn(name="auctionParamId")
private AuctionParam auctionParam;
#Basic
private String value;
}
public class AuctionParamValuePK {
private int auction;
private int auctionParam;
}
I think there are some errors in your Auction class. This is how I think it should look
#Entity
public class Auction {
#Id
private Integer auctionId;
#OneToMany(mappedBy="auction") // not auctionId
#MapKey(name="auctionParam") // not auctionParamId
private Map<AuctionParam, AuctionParamValue> values;
}
(The annotation values have to correspond with fields (or properties), not with columns)