Detached Entity passed to persist error - jpa

I have a #ManyToOne relationship:
#Entity
public class Produkt implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Basic
private String ausstattung;
#Basic
private String hersteller;
#Basic
private String name;
#Basic
private Boolean veraltet;
#ManyToOne(targetEntity = ProduktArt.class, cascade= CascadeType.PERSIST)
private ProduktArt typ;
#Basic
private String ausstattungsTyp;
// ...
}
#Entity
public class ProduktArt implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Basic
private String name;
#Basic
private Boolean sichtbarFuerKunde;
// ...
}
Which is persisted as below:
getEntityManager().persist(produkt);
It always throws this exception:
org.hibernate.PersistentObjectException: detached entity passed to
persist: ProduktArt
When I remove cascade = CascadeType.PERSIST:
org.hibernate.exception.ConstraintViolationException: could not
execute statement
How is this caused and how can I solve it?

Related

Error #OneToOne or #ManyToOne references an unknown entity

I receive an error like below and I do not know why?
Caused by: org.hibernate.AnnotationException: #OneToOne or #ManyToOne
on ##################.model.Orders.customerid references an unknown
entity: java.lang.Long
Class Orders
#Entity
public class Orders {
#Id
#GeneratedValue
private Long orderid;
#JoinColumn(name = "customerid", referencedColumnName = "CustomerID")
#ManyToOne
private Long customerid;
#JoinColumn(name = "employeeid", referencedColumnName = "EmployeeID")
#ManyToOne
private Long employeeid;
private java.sql.Timestamp orderdate;
private java.sql.Timestamp requireddate;
private java.sql.Timestamp shippeddate;
#JoinColumn(name = "shipperid", referencedColumnName = "ShipperID")
#ManyToOne
private Long shipvia;
private Double freight;
private String shipname;
private String shipaddress;
private String shipcity;
private String shipregion;
private String shippostalcode;
private String shipcountry;
#OneToMany(mappedBy="orderid")
private List<OrderDetails> orderDetails;
Class Customers
#Entity
public class Customers {
#Id
#GeneratedValue
private Long customerid;
private String companyname;
private String contactname;
private String contacttitle;
private String address;
private String city;
private String region;
private String postalcode;
private String country;
private String phone;
private String fax;
#OneToMany(mappedBy="customerid")
private List<Orders> orders;
Relation between this two entities are described here
Please explain me what am I doing wrong?
I found the reason after asking the question I apologize for the inconvenience. As You can see I forgot to change type for customerid it should by as follows
Class Orders
#Entity
public class Orders {
#Id
#GeneratedValue
private Long orderid;
#JoinColumn(name = "customerid", referencedColumnName = "CustomerID")
#ManyToOne
private Customers customerid;
#JoinColumn(name = "employeeid", referencedColumnName = "EmployeeID")
#ManyToOne
private Employees employeeid;
private java.sql.Timestamp orderdate;
private java.sql.Timestamp requireddate;
private java.sql.Timestamp shippeddate;
#JoinColumn(name = "shipperid", referencedColumnName = "ShipperID")
#ManyToOne
private Shippers shipvia;
private Double freight;
private String shipname;
private String shipaddress;
private String shipcity;
private String shipregion;
private String shippostalcode;
private String shipcountry;
#OneToMany(mappedBy="orderid")
private List<OrderDetails> orderDetails;
I had this error recently but with an unknown entity.
Initial SessionFactory creation failed.org.hibernate.AnnotationException: #OneToOne or #ManyToOne on XXXX.Terminal.location references an unknown entity: XXXX.dc.Location
Feb 06, 2020 11:51:38 AM org.apache.catalina.core.StandardContext listenerStart
In my case I had to add a mapping of this entity to the "hibernate.cfg.xml"
<mapping class="XXXX.dc.Location"/>

JPA query with OneToOne lazy

I have this structure of object
#Entity
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long memberId;
private String name;
private boolean man;
private String address;
#OneToOne(fetch = FetchType.LAZY)
private City city;
private String postalCode;
private String phone1;
private String phone2;
private LocalDate birthdate;
private String email;
private String emergencyContactName;
private String emergencyPhone;
private String paymentGatewayKey;
#OneToMany(fetch = FetchType.LAZY)
private List<Contract> contracs;
#OneToOne(fetch = FetchType.LAZY)
private Commerce commerce;
}
#Entity
public class Contract {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long contractId;
private BigDecimal price;
private int frequency;
private int term;
private LocalDate startDate;
private LocalDate endDate;
private int numberOfPayment;
#Enumerated(EnumType.STRING)
private StatusEnum status;
#OneToMany(fetch = FetchType.LAZY,mappedBy = "contract")
private List<Payment> payments;
#ManyToOne
private Member member;
}
#Entity
public class Payment {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long paymentId;
private BigDecimal price;
private LocalDate date;
#Enumerated(EnumType.STRING)
private StatusEnum status;
#Enumerated(EnumType.STRING)
private PaymentModeEnum paymentMode;
#ManyToOne
private Contract contract;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private List<Operation> operations;
}
is it possible from a member query to get only the needed contract, payment, city and commerce info?
If member have many contract... i want to get only contract #2...
I started this query but city and commerce are lazy and i don't know what to do with theses fields.
select m from Member m inner join fetch m.contracs c inner join fetch c.payments p where c.contractId = :contractId

How to handle compound key with relationship in JPA2 and Spring Data JPA?

I have a problem to handle mapping object relationship for mysql tables.
I have 2 tables shown below:
Device
-----------
deviceId PK
deviceName
ApkInfo
--------
id PK
packageName
appName
deviceId FK
And then here are my classes:
#Entity
#Table(name="Device")
public class Device implements Serializable {
#Column
#Id
private String deviceId;
#Column
private String deviceName;
//getters and setters
}
#Entity
#Table(name="ApkInfos")
public class ApkInfo implements Serializable {
#Column
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column
#Id
private String packageName;
#Column
private String appName;
#Column
#Temporal(TemporalType.TIMSTAMP)
private Date installDate;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
This works for me, but I want to use compound key, deviceId and packageName, in ApkInfos table.
#Entity
#Table(name="ApkInfos")
public class ApkInfo implements Serializable {
#Colum(instable=false, updatable=false)
#Id
private String deviceId;
#Column
private String packageName;
#Column
private String appName;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId")
private Device device;
//getters and setters
}
But when I tried to save an entity using Spring Data JPA repository, I got an error:
org.springframework.dao.InvalidAccessApiUsageException: Class must not
be null, nested exception is java.lang.IllegalArgumentException: Class
must not be null
ApkInfo apkInfo = new ApkInfo();
apkInfo.setDeviceId("1234");
apkInfo.setPackageName("aaa");
apkInfo.setAppName("myapp");
apkInfo.setInstallDate(new Date());
apkInfo.setDevice(new Device("1234"));
repository.save(apkInfo);
And device has the deviceID '1234' already exists in the Device table.
I created a separate primary key class added #IdClass in the ApkInfo class. It works fine now, thanks. I am going to have a look at EmbeddedId more later.
I added #IdClass at the entity class and #Id for the packageName property. Also I made insert, update false for the One-to-many column.
#Entity
#Table(name="ApkInfos")
#IdClass(ApkInfo.class)
public class ApkInfo implements Serializable {
#Column #Id private String deviceId;
#Column #Id private String packageName;
#ManyToOne
#JoinColumn(name="deviceId" referencedColumnName="deviceId", insetable=false, updatable=false)
private Device device;
//getters and setters missing
}
Primary key class has only setters and overrides equals and hasCode methods.
public class ApkInfo implements Serializable {
private String deviceId;
private String packageName;
public ApkInfo(){}
public ApkInfo (String deviceId, String packageName){
this.deviceId = deviceId;
this.packageName = packageName;
}
public String getDeviceId(){
return this.deviceId;
}
public String getPackageName(){
return this.packageName;
}
#Override
public boolean equals(Object obj){
return (obj!=null &&
obj instanceof ApkInfoPk &&
deviceId.equals(((ApkInfoPk)obj).getDeviceId()) &&
packageNames.equals(((ApkInfoPk)obj).getPackageName()) );
}
#Override
public int hashCode(){
super.hashCode();
}
}

how to access to subproperties with jpa metamodel in where clause

I have a two entities with relation between they are.
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Integer id;
#NotNull
#Size(min = 3, max = 25)
private String firstName;
#NotNull
#Size(min = 3, max = 25)
private String lastName;
private String login;
private String password;
#OneToMany(mappedBy = "client")
private List<Project> projects;
}
and
public class Project implements Serializable {
private static final long serialVersionUID = 4762714047114442539L;
#Id
#GeneratedValue
private Integer id;
private String name;
#Temporal(TemporalType.TIMESTAMP)
private Date startDate;
#ManyToOne
#JoinColumn
private Client client;
}
I want to made a query using jpametamodel and Criteria API. Like this:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Project> q = cb.createQuery(Project.class);
Root<Project> projects = q.from(Project.class);
q.where(cb.equal(projects.get(Project_.client), clientId));
Problem for me that i don't know how to get access to "id" property of Client in this string:
q.where(cb.equal(projects.get(Project_.client), clientId));
i want to get something like
q.where(cb.equal(projects.get("client.id"), clientId));
but with jpametamodel. It is possible? :)
Tried something like this?
projects.get(Project_.client).get(Client_.id);

JPA #OneToMany and composite PK

I am working on a JPA project. I need to use a #OneToMany mapping on a class that has three primary keys. You can find the errors and the classes after this.
javax.persistence.PersistenceException: No Persistence provider for EntityManager named JTA_pacePersistence: Provider named oracle.toplink.essentials.PersistenceProvider threw unexpected exception at create EntityManagerFactory:
javax.persistence.PersistenceException
javax.persistence.PersistenceException: Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: predeploy for PersistenceUnit [JTA_pacePersistence] failed.
Internal Exception: Exception [TOPLINK-7220] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [private java.util.Set isd.pacepersistence.common.Action.permissions] from the entity class [class isd.pacepersistence.common.Action] is incomplete. When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns. Both the name and the referenceColumnName elements must be specified in each such #JoinColumn.
at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:643)
at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:196)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:110)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
at isd.pacepersistence.common.DataMapper.(Unknown Source)
at isd.pacepersistence.server.MainServlet.getDebugCase(Unknown Source)
at isd.pacepersistence.server.MainServlet.doGet(Unknown Source)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:290)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
Here is the source code of my classes :
Action :
#Entity
#Table(name="action")
public class Action {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int num;
#ManyToOne(cascade= { CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH })
#JoinColumn(name="domain_num")
private Domain domain;
private String name;
private String description;
#OneToMany
#JoinTable(name="permission", joinColumns= { #JoinColumn(name="action_num", referencedColumnName="action_num", nullable=false, updatable=false) }, inverseJoinColumns= { #JoinColumn(name="num") })
private Set<Permission> permissions;
public Action() {
}
Permission :
#SuppressWarnings("serial")
#Entity
#Table(name="permission")
public class Permission implements Serializable {
#EmbeddedId
private PermissionPK primaryKey;
#ManyToOne
#JoinColumn(name="action_num", insertable=false, updatable=false)
private Action action;
#ManyToOne
#JoinColumn(name="entity_num", insertable=false, updatable=false)
private isd.pacepersistence.common.Entity entity;
#ManyToOne
#JoinColumn(name="class_num", insertable=false, updatable=false)
private Clazz clazz;
private String kondition;
public Permission() {
}
PermissionPK :
#SuppressWarnings("serial")
#Entity
#Table(name="permission")
public class Permission implements Serializable {
#EmbeddedId
private PermissionPK primaryKey;
#ManyToOne
#JoinColumn(name="action_num", insertable=false, updatable=false)
private Action action;
#ManyToOne
#JoinColumn(name="entity_num", insertable=false, updatable=false)
private isd.pacepersistence.common.Entity entity;
#ManyToOne
#JoinColumn(name="class_num", insertable=false, updatable=false)
private Clazz clazz;
private String kondition;
public Permission() {
}
Good morning,
After a long day searching how JPA and #OneToMany works with composite PK, I did find a solution. In order to make it work, I used the parameter mappedBY of #OneToMany. As you can see in the code sample, I mapped the Set of Permission with the attribute action of the class Permission. And that's it! Simple when you know it!
FF
Action Class :
#Entity
#Table(name="action")
public class Action {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int num;
#ManyToOne(cascade= { CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH })
#JoinColumn(name="domain_num")
private Domain domain;
private String name;
private String description;
#OneToMany(mappedBy="action")
private Set<Permission> permissions;
Permission Class
#SuppressWarnings("serial")
#Entity
#Table(name="permission")
public class Permission implements Serializable {
#EmbeddedId
private PermissionPK primaryKey;
#ManyToOne
#JoinColumn(name="action_num", insertable=false, updatable=false)
private Action action;
The error message seems pretty clear: you need to declare the three columns of your composite PK as #JoinColum and the name and referenceColumnName must be specified for each. I didn't test the mapping but try this:
#OneToMany
#JoinTable(name="permission", joinColumns= {
#JoinColumn(name="col1", referencedColumnName="col1", nullable=false, updatable=false),
#JoinColumn(name="col2", referencedColumnName="col2", ...),
#JoinColumn(name="col3", referencedColumnName="col3", ...)
}, inverseJoinColumns= { #JoinColumn(name="num") })
private Set<Permission> permissions;