Can't persist with Hibernate and 3 relationed tables - java

I have 3 tables:
Principals: PK -> PrincipalID
Roles_type: PK -> roles_type
Roles: PK -> PrincipalID (Foreign Key), PK -> Role (Foreign Key).
My Entity are:
PRINCIPALS
#Entity
#Table(name = "principals")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Principals implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#javax.persistence.GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "PrincipalID", nullable = false)
private String principalID;
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL, mappedBy = "principals")
private Collection<Roles> rolesCollection;
}
ROLES
#Entity
#Table(name = "roles")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Roles implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected RolesPK rolesPK;
#Column(name = "RoleGroup")
private String roleGroup;
#JoinColumn(name = "Role", referencedColumnName = "roles_type", insertable = false, updatable = false)
#ManyToOne(optional = false)
private RolesType rolesType;
#JoinColumn(name = "PrincipalID", referencedColumnName = "PrincipalID", insertable = false, updatable = false)
#ManyToOne(fetch = FetchType.EAGER)
private Principals principals;
}
ROLESPK
#Embeddable
public class RolesPK implements Serializable {
#Column(name = "PrincipalID", nullable = false)
private String principalID;
#Column(name = "Role", nullable = false)
private String role;
}
ROLES_TYPE
#Entity
#Table(name = "roles_type")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class RolesType implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "roles_type")
private String rolesType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "rolesType")
private Collection<Roles> rolesCollection;
}
My code for persist a new principals:
Principals principals = new Principals();
principals.setPrincipalID("PRINCIPAL");
RolesType rolesType = em.find(RolesType.class, "TYPE_1");
RolesPK rolesPk = new RolesPK();
rolesPk.setPrincipalID(principals.getPrincipalID());
rolesPk.setRole(rolesType.getRolesType());
Collection<Roles> collRoles = new ArrayList<Roles>();
Roles roles = new Roles();
roles.setRolesType(rolesType);
roles.setRolesPK(rolesPk);
roles.setPrincipals(principals);
collRoles.add(roles);
principals.setRolesCollection(collRoles);
rolesType.setRolesCollection(collRoles);
em.persist(principals);
So I get:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: package.entity.Principals
I tried many combinations (persist roles, change CascadeType etc...)
Please help me :-)

Resolved:
I changed Principals.java from
#Id
#javax.persistence.GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "PrincipalID", nullable = false)
to
#Id
#Basic(optional = false)
#Column(name = "PrincipalID")

Related

Got java "stackoverflow" when join two tables

I have two java entity classes :
#Table(name = "user")
public class UserEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
#JoinColumn(name = "opportunity_id")
private OpportunityEntity opportunity;
}
and
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
When i search for a list of Users [find users], i've got a "stackoverflow" when mapping User.opportunity.
the bug was clear that the opportunity.mainUser refer to User which itself refer to the same opportunity.
Is there another way to design my models ?
For example create a boolean isMain in User Model ?
Try to specify relationship to UserEntity by adding mappedBy to annotatation
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne(mappedBy="opportunity")
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}

Referential integrity constraint violation error in JPA

I am trying to parse a web request and save to database. I have 3 models and first node is virtualDocument. This is the uniq table (according to request url). VirtualRequest table has all erquest bodies and HttpHeaderList table has all thhp headers according to their virtualRequest bean id.
when I tried to save the first log I got and error like this;
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK1TW2G47F7A47580KQVMDJWGBQ: PUBLIC.T_VIRTUAL_REQUEST FOREIGN KEY(REQUEST_ID) REFERENCES PUBLIC.T_VIRTUAL_DOCUMENT(DOCUMENT_ID) (65)"; SQL statement:
insert into t_virtual_request (request_id, media_type, method_type, request_url) values (null, ?, ?, ?) [23506-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.192.jar:1.4.192]
here is VirtualDocument bean
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "request_id")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "response_id")
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
here is VirtualRequest bean;
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "header_id")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
here is HeaderList bean;
#Entity
#Table(name = "t_http_headers")
public class HttpHeaderList {
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
}
I think this is what you want instead:
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
// Note the mappedBy parameter. This points to the property in the entity that owns the relationship (in this case the VirtualResponse).
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "document_id")
private VirtualDocument virtualDocument;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualRequest")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
#Entity
#Table(name = "t_http_headers")
public class HttpHeader { /*Note this is a more appropriate name for the entity since it holds the data of a single header.*/
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "request_id")
private VirtualRequest virtualRequest
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "response_id")
private VirtualResponse virtualResponse;
}
Updated the answer to add mapping the headers to the request entity.

JPA unidirectional one to many with join table - entity mapping not working

I have tried to create some JPA Entities for a DB designed with the following tables: PRINCIPALS and CREDENTIALS which have the following relations with other tables:
#Entity
#Table(name = "CREDENTIALS")
public class Credentials {
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#OneToOne
#JoinColumn(name = "CREDENTIAL_TYPE_ID", insertable = false, updatable = false)
private CredentialTypes credentialTypes;
}
CREDENTIALS has a oneToOne relation with CREDENTIAL_TYPES
#Entity
#Table(name = "CREDENTIAL_TYPES")
public class CredentialTypes {
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
#Column(name = "DESCRIPTION")
private String description;
}
#Entity
#Table(name = "PRINCIPALS")
public class Principals implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#OneToOne
#JoinColumn(name = "PRINCIPAL_TYPE_ID", insertable = false, updatable = false)
private PrincipalTypes principalTypes;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "PRINCIPAL_CREDENTIAL",
joinColumns = #JoinColumn(name = "CREDENTIAL_ID"),
inverseJoinColumns = #JoinColumn(name = "PRINCIPAL_ID"))
private List<Credentials> credentials;
PRINCIPALS has a oneToOne relation with PRINCIPAL_TYPES
#Entity
#Table(name = "PRINCIPAL_TYPES")
public class PrincipalTypes implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "DESCRIPTION")
private String description;
And finally PRINCIPALS has a oneToMany relation with CREDENTIALS and uses a join table PRINCIPLE_CREDENTIAL
#Entity
#Table(name = "PRINCIPAL_CREDENTIAL")
public class PrincipalCredential implements Serializable {
#Id
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Id
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#Id
#Column(name = "CREDENTIAL_ID")
private Integer credentialID;
#Id
#Column(name = "CREDENTIAL_TYPE_ID")
private String credentialTypeID;
At startup (using SpringBoot) I receive an error for the oneToMany relation between Principals and Credentials and just don't have any idea how to fix it... Tried various other methods (The DB design cannot be changed).
Caused by: org.hibernate.AnnotationException: A Foreign key refering entities.Principals from entities.Credentials has the wrong number of column. should be 2
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:502)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1467)
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1233)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:794)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:729)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:85
I find the exception wierd because there is no refering of Principlas from Credentials....
PRINCIPLE_TYPE_ID and CREDENTIAL_TYPE_ID are missing in the joinColumns/inverseJoinColumns. I think you must use the #JoinColumns Annotation

Netbeans #JoinColoumns error with auto generated entity class

I've creating entities from a data-source using Netbeans 7.4.
And I have an error which arises with all entities which have a composite primary key. The error can be seen below.
I have searched this problem on stack-overflow and its is usually because people have not defined the join columns. but I have this done. I'm also unsure how there is errors in code generated by netbeans.
Here is an image of my MySQL database which I forward engineered to create these entitys:
Any help would be greatly appreciated !
Here is the only the relevant code
Absence entity:
public class Absence implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected AbsencePK absencePK;
#Basic(optional = false)
#NotNull
#Column(name = "idAbsence")
private int idAbsence;
#Basic(optional = false)
#NotNull
#Column(name = "Date")
#Temporal(TemporalType.DATE)
private Date date;
#Size(max = 35)
#Column(name = "type")
private String type;
#Lob
#Size(max = 65535)
#Column(name = "remark")
private String remark;
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Timetable timetable;
#JoinColumn(name = "Student_idStudent", referencedColumnName = "idStudent", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Student student;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
AbsencePK entity:
#Embeddable
public class AbsencePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
#Basic(optional = false)
#NotNull
#Column(name = "Student_idStudent")
private int studentidStudent;
#Basic(optional = false)
#NotNull
#Column(name = "TimeTable_Period")
private int timeTablePeriod;
public AbsencePK() {
}
public AbsencePK(int classidClass, int studentidStudent, int timeTablePeriod) {
this.classidClass = classidClass;
this.studentidStudent = studentidStudent;
this.timeTablePeriod = timeTablePeriod;
}
Error:
Caused by: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field timetable] from the entity class [class com.fyp.simstest.Absence] 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 referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1847)
EDIT
TimeTable
#Entity
#Table(name = "timetable")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Timetable.findAll", query = "SELECT t FROM Timetable t"),
#NamedQuery(name = "Timetable.findByPeriod", query = "SELECT t FROM Timetable t WHERE t.timetablePK.period = :period"),
#NamedQuery(name = "Timetable.findByDay", query = "SELECT t FROM Timetable t WHERE t.timetablePK.day = :day"),
#NamedQuery(name = "Timetable.findByClassidClass", query = "SELECT t FROM Timetable t WHERE t.timetablePK.classidClass = :classidClass")})
public class Timetable implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TimetablePK timetablePK;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "timetable")
private Collection<Absence> absenceCollection;
#JoinColumn(name = "Class_idClass", referencedColumnName = "idClass", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Class class1;
public Timetable() {
}
public Timetable(TimetablePK timetablePK) {
this.timetablePK = timetablePK;
}
TimetablePK
Embeddable
public class TimetablePK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "Period")
private int period;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "Day")
private String day;
#Basic(optional = false)
#NotNull
#Column(name = "Class_idClass")
private int classidClass;
public TimetablePK() {
}
public TimetablePK(int period, String day, int classidClass) {
this.period = period;
this.day = day;
this.classidClass = classidClass;
}
EDIT TWO
Your diagram indicates the TimeTable table has a primary key composed of three columns (Period, Day, and Class_idClass). You will need to add an annotation to Absence.timeTable that looks something like this:
public class Absence implements Serializable {
...
#JoinColumns[
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period", ...),
#JoinColumn(name = "????", referencedColumnName = "Day", ...),
#JoinColumn(name = "Class_idClass", referencedColumnName = "Class_idClass", ...)
]
#ManyToOne(optional = false)
private TimeTable timeTable;
...
}
Consider this:
#JoinColumn(name = "TimeTable_Period", referencedColumnName = "Period")
private Timetable timetable;
You have referenced to the column Period at your Timetable entity. But in the Timetable.java I don't see any field that is mapped with your Period column of your table.
For example:
#Id // as its the primary key!
#Column(name="Period")
private Long period
This should be same for other referenced entities those you have used with your #ManyToOne mapping.

JPA - Issues removing child entities on bidirectional mapping

I need to remove a child entity called "SystemParamater" based on the it´s id.
What i was trying to do:
- Begin Tran
SystemParameter param EntityManager.find(SystemParameter.class,<paremeter.id>)
EntityManager.remove(param)
-Commit tran
But the entity was not removed.
What´s the correct way to remove a child entity?
Below, you could find my entities:
SystemParameter:
#Entity
#Table(name = "system_parameters")
#Cacheab le
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SystemParameter extends BasicEntity {
private static final long serialVersionUID = -6416605270912358340L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "paramName", length = 50, nullable = false)
private String paramName;
#Column(name = "paramValue", length = 255, nullable = false)
private String paramValue;
#Column(name = "encrypted", nullable = false)
#Type(type = "yes_no")
private Boolean encrypted = Boolean.FALSE;
#ManyToOne
#JoinColumn(name = "groupId", nullable = false)
private SystemParameterGroup parameterGroup;
}
SystemParameterGroup:
#Entity
#Table(name = "system_parameter_groups", uniqueConstraints = { #UniqueConstraint(columnNames = { "searchKey" }) })
#Cacheable
public class SystemParameterGroup extends BasicEntity {
private static final long serialVersionUID = -1762633144642103487L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", length = 50, nullable = false)
private String name;
/**
* Description.
*/
#Column(name = "description", length = 255, nullable = false)
private String description;
/**
* Search key.
*/
#Column(name = "searchKey", length = 50, nullable = false)
private String searchKey;
/**
* System parameter list.
*/
#OneToMany(fetch = FetchType.EAGER, mappedBy = "parameterGroup", cascade = CascadeType.ALL, orphanRemoval = true)
#OrderBy("paramName")
private List<SystemParameter> systemParameterList;
}
You have to remove the SystemParameter entity also from the SystemParameterGroup's list of SystemParameter:
systemParameterGroup.getSystemParameterList().remove(systemParameter);
This issue is related to this one.

Categories

Resources