org.hibernate.MappingException - composite id - java

In my Spring boot - JPA application, I am trying to implement composite key :
#Entity
public class User
{
#Id
private String timeStamp;
#Id
private String firstName;
#Id
private String lastName;
}
This gives me error, saying :
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Composite-id class must implement Serializable: com.mua.testkeys.model.User
Even if I implement Serializable it gives me error.
How can I resolve this ?
Used : Spring + JPA + H2

Composite Key can be created with #IdClass as below.
User.class
#IdClass(UserPK.class)
#Table(name = "user")
#Entity
public class User {
#Id
private String timeStamp;
#Id
private String firstName;
#Id
private String lastName;
//remaining fields
// getters and setters
}
UserPK.class
public class UserPK {
private String timeStamp;
private String firstName;
private String lastName;
// constructors
// getters and setters
//implement euquels() and hashcode()
}
Define a Class for primary key with all keys as fields.
Implement equals() and hashcode() methods.
Annotate User class with #IdClass(UserPK.class)
Declare Id fields with #Id annotation

Related

Can't create composite primary key: Unable to build Hibernate SessionFactory

I try to create a composite primary key but can't.
My attempt (there is the tutorial I used):
User entity:
#Entity
#Table(name = "user")
public class User {
#Id
#Column
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column
private String name;
//getters, setters, equals, hashcode
}
PersonalScore class:
#Entity
public class PersonalScore {
#EmbeddedId
private PersonalScoreId personalScoreId;
//getters, setters, equals, hashcode, constructors
}
PersonalScoreId class (Primary key):
#Embeddable
public class PersonalScoreId implements Serializable {
private User user;
private Date date;
//getters, setters, equals, hashcode, constructors (noargs included)
That's all. In the result I got the error:
> Caused by: javax.persistence.PersistenceException: [PersistenceUnit:
> default] Unable to build Hibernate SessionFactory; nested exception is
> org.hibernate.MappingException: Could not determine type for:
> com...model.dto.User, at table: personal_score, for columns:
> [org.hibernate.mapping.Column(user)]
From EmbeddedId:
Relationship mappings defined within an embedded id class are not supported.
What you need to do is replace the User field with a field for the user's id (private long userId), then use MapsId in your PersonalScore class to add a relation with User using the userId field from the embedded id.

JPA Problem, Using Parent Entity's Primary Key for Child's Entity's Primary Key

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

Trying Derived Identifiers using #JoinedColumns, got error Attempt to modify an identity column

This is my sql table structure:
create table TBL_EMPLOYEE_FIVE(
EMP_ID integer generated always as identity(start with 50, increment by 4),
NAME varchar(50),
COUNTRY varchar(50),
MGR_ID integer,
MGR_COUNTRY varchar(50),
constraint PK_COMPOSIT_001AD primary key(EMP_ID,COUNTRY),
constraint FK_COMPO_00123 foreign key(MGR_ID,MGR_COUNTRY) references TBL_EMPLOYEE_FIVE
)
And this is my entity mapping:
#Entity
#Table(name="TBL_EMPLOYEE_FIVE")
#IdClass(EmployeeId.class)
public class EmployeeOne implements Serializable{
public EmployeeOne(){}
public EmployeeOne(String employeeName,String empCountry){
this.empCountry = empCountry;
this.employeeName = employeeName;
}
public EmployeeOne(String employeeName,String empCountry,EmployeeOne manager){
this.empCountry = empCountry;
this.employeeName = employeeName;
this.manager = manager;
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="EMP_ID")
private Integer employeeId;
#Id
#Column(name="COUNTRY")
private String empCountry;
#Column(name="NAME")
private String employeeName;
#ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.PERSIST},
fetch= FetchType.LAZY,
targetEntity=EmployeeOne.class)
#JoinColumns({
#JoinColumn(name="MGR_ID",referencedColumnName="EMP_ID"),
#JoinColumn(name="MGR_COUNTRY",referencedColumnName="COUNTRY")
})
private EmployeeOne manager;
#OneToMany(cascade={CascadeType.PERSIST, CascadeType.PERSIST},mappedBy="manager")
private Set<EmployeeOne> employees;
// getters and setters,
}
This is the the embedded id mapping,
#Embeddable
public class EmployeeId implements Serializable{
public EmployeeId(){}
public EmployeeId(Integer employeeId,String empCountry){
this.employeeId = employeeId;
this.empCountry = empCountry;
}
#Column(name="EMP_ID")
private Integer employeeId;
#Column(name="COUNTRY")
private String empCountry;
// only getters and implementation of hashcode and equals method
}
And this is what I am trying to run in my main method:
EmployeeOne manager = new EmployeeOne("Yousuf Ahmadinejad", "IRAN");
em.persist(manager);
But here i am getting an exception i.e.
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: Attempt to modify an identity column 'EMP_ID'.
It's not like i didn't understood the exception,
but why this exception occured in the first place? I already annotated it with #GenerateValue for Empid and I am not setting the empId manually. Does this exception occur because I have combined primary key as empId and country, and than the empId is autogenerated using Identity, hence its giving an exception ?
Can you please tell me whats going wrong
One more thing i want to add here is, if i removed #Column and #Embeddeble annotation for EmployeeId.java, and than run, i get an following exception,
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.entities.derived.EmployeeId.employeeId
So just trying to find the solution to persist employee keeping the autogenerated Id as it is
First Hibernate does not generate id's for composite keys, so you should change EmployeeOne to:
#Id
//#GeneratedValue(strategy=GenerationType.IDENTITY) remove this line
#Column(name="EMP_ID")
private Integer employeeId;
Second that's not how you should implement EmployeeId composite key class. See: https://stackoverflow.com/a/3588400/1981720
Third, the exception is thrown by the database, not Hibernate. Check if you're getting the same exception with another database.

JPA Mapping Error -not provided sufficient metadata in your id class

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)

#OneToOne annotation within composite key class is not working

Maybe somebody can clarify what is wrong with the code below. When I create one-to-one association within embedded class (it is composite primary key) like in the code below:
#Entity
public class Test {
#EmbeddedId
private TestId id;
#Embeddable
public static class TestId implements Serializable {
private static final long serialVersionUID = 1950072763330622759L;
#OneToOne(optional = false)
#JoinColumn(name = "linkedTable_id")
private LinkedTable linkedTable;
}
..........
}
I get the following stack trace:
--------------------------------------------
Caused by: java.lang.NullPointerException
at org.hibernate.cfg.AnnotationBinder.bindOneToOne(AnnotationBinder.java:1867)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1286)
at org.hibernate.cfg.AnnotationBinder.fillComponent(AnnotationBinder.java:1662)
at org.hibernate.cfg.AnnotationBinder.bindId(AnnotationBinder.java:1695)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1171)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:706)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:452)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:268)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1121)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1211)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:154)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:847)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:178)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:235)
... 26 more
What is interesting why the sample above works if I change association type to many-to-one and doesn't work with one-to-one?
I wasn't aware this was possible but, according to the Hibernate Annotation reference documentation, it is (this is Hibernate specific though):
2.2.3.2.1. #EmbeddedId property
(...)
While not supported in JPA, Hibernate
lets you place your association
directly in the embedded id component
(instead of having to use the
#MapsId annotation).
#Entity
class Customer {
#EmbeddedId CustomerId id;
boolean preferredCustomer;
}
#Embeddable
class CustomerId implements Serializable {
#OneToOne
#JoinColumns({
#JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
#JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
})
User user;
String customerNumber;
}
#Entity
class User {
#EmbeddedId UserId id;
Integer age;
}
#Embeddable
class UserId implements Serializable {
String firstName;
String lastName;
}
And with the code you provided, the following snippet just works for me:
LinkedTable linkedTable = new LinkedTable();
linkedTable.setId(1l);
session.persist(linkedTable);
session.flush();
Test.TestId testId = new Test.TestId();
testId.setLinkedTable(linkedTable);
Test test = new Test();
test.setId(testId);
session.persist(test);
session.flush();
Tested with Hibernate EM 3.4.0.GA, Hibernate Annotations 3.4.0.GA and Hibernate Core 3.3.0.SP1.
If it doesn't work for you, can you provide a bit more code allowing to reproduce the problem?

Categories

Resources