While this JPQL is working without any exception
Query query = em.createQuery("SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h
WHERE h.request = r
AND (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee ORDER BY r.objid DESC");
this JPQL is not working and throws NullPointerException
Query query = em.createQuery("SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h
ON h.request = r
WHERE (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee ORDER BY r.objid DESC");
The only difference between these two JPQL is ON Clause.
And yes there is 1:N relation between Request and Requesthistory in both entities and tables.
Here is exception I got:
Exception Description: Query failed to prepare, unexpected error occurred: [java.lang.NullPointerException].
Internal Exception: java.lang.NullPointerException
Query: ReportQuery(referenceClass=Request jpql="SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h ON h.request = r WHERE (r.responsible = :employee OR h.employee = :employee) AND r.requestedby != :employee ORDER BY r.objid DESC")
at org.eclipse.persistence.exceptions.QueryException.prepareFailed(QueryException.java:1590) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:680) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:901) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:613) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:194) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:102) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:86) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1603) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at com.kadir.dao.notification.RequestDao.findToUserRequests(RequestDao.java:44) [classes:]
at com.kadir.service.notification.RequestService.getToUserRequests(RequestService.java:43) [classes:]
at com.kadir.bean.notification.RequestBean.init(RequestBean.java:49) [classes:]
... 110 more
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.expressions.ObjectExpression.getOwnedTables(ObjectExpression.java:583) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:294) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:3275) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:369) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.FieldExpression.normalize(FieldExpression.java:223) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:224) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:574) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:865) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.expressions.ExpressionBuilder.normalize(ExpressionBuilder.java:267) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:825) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:232) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:224) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1449) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:641) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:586) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareReportQuerySelectAllRows(ExpressionQueryMechanism.java:1694) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReportQuery.prepareSelectAllRows(ReportQuery.java:1203) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:744) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1071) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:661) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
... 120 more
What am I doing wrong?
UPDATE FOR ENTITIES
Request.java
package com.kadir.entity.notification;
import com.kadir.entity.Base;
import com.kadir.entity.humanresource.Employee;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the REQUEST database table.
*
*/
#Cacheable
#Entity
#Table(name="REQUEST", schema="NOTIFICATION")
#NamedQuery(name="Request.findAll", query="SELECT r FROM Request r")
public class Request extends Base implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="CONTENT")
private String content;
#ManyToOne
#JoinColumn(name="REQUESTEDBY")
private Employee requestedby;
#ManyToOne
#JoinColumn(name="RESPONSIBLEOBJID")
private Employee responsible;
#Column(name="TITLE")
private String title;
//bi-directional many-to-one association to Requesttype
#ManyToOne
#JoinColumn(name="REQUESTTYPEOBJID")
private Requesttype requesttype;
//bi-directional many-to-one association to Responsetype
#ManyToOne
#JoinColumn(name="RESPONSETYPEOBJID")
private Responsetype responsetype;
//bi-directional many-to-one association to Requesthistory
#OneToMany(mappedBy="request")
private List<Requesthistory> requesthistories;
public Request() {
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
public Employee getRequestedby() {
return this.requestedby;
}
public void setRequestedby(Employee requestedby) {
this.requestedby = requestedby;
}
public Employee getResponsible() {
return this.responsible;
}
public void setResponsible(Employee responsible) {
this.responsible = responsible;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Requesttype getRequesttype() {
return this.requesttype;
}
public void setRequesttype(Requesttype requesttype) {
this.requesttype = requesttype;
}
public Responsetype getResponsetype() {
return this.responsetype;
}
public void setResponsetype(Responsetype responsetype) {
this.responsetype = responsetype;
}
public List<Requesthistory> getRequesthistories() {
return this.requesthistories;
}
public void setRequesthistories(List<Requesthistory> requesthistories) {
this.requesthistories = requesthistories;
}
public Requesthistory addRequesthistory(Requesthistory requesthistory) {
getRequesthistories().add(requesthistory);
requesthistory.setRequest(this);
return requesthistory;
}
public Requesthistory removeRequesthistory(Requesthistory requesthistory) {
getRequesthistories().remove(requesthistory);
requesthistory.setRequest(null);
return requesthistory;
}
}
RequestHistory.java
package com.kadir.entity.notification;
import com.kadir.entity.humanresource.Employee;
import com.kadir.entity.Base;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the REQUESTHISTORY database table.
*
*/
#Cacheable
#Entity
#Table(name="REQUESTHISTORY", schema="NOTIFICATION")
#NamedQuery(name="Requesthistory.findAll", query="SELECT r FROM Requesthistory r")
public class Requesthistory extends Base implements Serializable {
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name="EMPLOYEEOBJID")
private Employee employee;
#Column(name="EXPLANATION")
private String explanation;
//bi-directional many-to-one association to Request
#ManyToOne
#JoinColumn(name="REQUESTOBJID")
private Request request;
//bi-directional many-to-one association to Responsetype
#ManyToOne
#JoinColumn(name="RESPONSETYPEOBJID")
private Responsetype responsetype;
public Requesthistory() {
}
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getExplanation() {
return this.explanation;
}
public void setExplanation(String explanation) {
this.explanation = explanation;
}
public Request getRequest() {
return this.request;
}
public void setRequest(Request request) {
this.request = request;
}
public Responsetype getResponsetype() {
return this.responsetype;
}
public void setResponsetype(Responsetype responsetype) {
this.responsetype = responsetype;
}
}
Base.java
package com.kadir.entity;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
#Cacheable
#MappedSuperclass
public abstract class Base {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "OBJID")
private BigInteger objid;
#Column(name = "CREATEDBY")
private String createdby;
#Column(name = "CREATEDDATE")
private Timestamp createddate;
#Version
#Column(name = "ROWVERSION")
private Integer rowversion;
#Column(name = "UPDATEDBY")
private String updatedby;
#Column(name = "UPDATEDDATE")
private Timestamp updateddate;
#Column(name = "ARCHIVED", columnDefinition = "int default 0")
private int archived;
public BigInteger getObjid() {
return this.objid;
}
public void setObjid(BigInteger objid) {
this.objid = objid;
}
public String getCreatedby() {
return this.createdby;
}
public void setCreatedby(String createdby) {
this.createdby = createdby;
}
public Date getCreateddate() {
return this.createddate;
}
public void setCreateddate(Timestamp createddate) {
this.createddate = createddate;
}
public Integer getRowversion() {
return this.rowversion;
}
public void setRowversion(Integer rowversion) {
this.rowversion = rowversion;
}
public String getUpdatedby() {
return this.updatedby;
}
public void setUpdatedby(String updatedby) {
this.updatedby = updatedby;
}
public Timestamp getUpdateddate() {
return this.updateddate;
}
public void setUpdateddate(Timestamp updateddate) {
this.updateddate = updateddate;
}
public int getArchived() {
return archived;
}
public void setArchived(int archived) {
this.archived = archived;
}
}
I think problem is with your inheritance mapping.
The mapped supperclass Base has no inheritance strategy defined, so default one SINGLE_TABLE is used. Next you define #Table(name="...") annotations on each of your sublcasses Request and Requesthistory what makes no sense with SINGLE_TABLE strategy as with this strategy all subclasses are mapped to one shared table.
I think TABLE_PER_CLASS is the strategy you want.
#Cacheable
#MappedSuperclass
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Base {
Update after closer look at your query
In jpql join clauses are used a little bit different as in sql. You can not join arbitrary entities and then bind them through ON or WHERE clause. You can join only entities associated in abstract schema.
Try following (jpql valid) query:
SELECT DISTINCT(r)
FROM Request r
LEFT JOIN r.requesthistories h
WHERE (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee
ORDER BY r.objid DESC
(Note: Queries over non-associated entities are posssible, but it is different topic.)
Related
If I save this entity using JPA repository with a new defaultAssetId, it will only update the defaultAsssetId to the new value if I set defaultAsset as well. I want to be able to save without setting defaultAsset.
Same problem applies to taskType and assetRole.
package au.com.polonious.conf.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
#Entity
public class TaskTypeAssetRole implements Serializable {
#GenericGenerator(name="tasktypeassetroleidseq",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "tasktypeassetroleidseq"),
#Parameter(name = "initial_value", value = "1"),
#Parameter(name = "increment_size", value = "1")
})
#Id
#GeneratedValue(generator = "tasktypeassetroleidseq")
private Long id;
#Column(insertable = false, updatable=false)
private Long taskTypeId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="tasktypeid")
private TaskType taskType;
#Column(insertable = false, updatable=false)
private Long assetRoleId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="assetRoleId")
private Role assetRole;
#Column(insertable = false, updatable=false)
private Long defaultAssetId;
#Fetch(FetchMode.JOIN)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="defaultassetid")
private Asset defaultAsset;
private Date startDate;
private Date endDate;
private String notes;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getTaskTypeId() {
return taskTypeId;
}
public void setTaskTypeId(Long taskTypeId) {
this.taskTypeId = taskTypeId;
}
public TaskType getTaskType() {
return taskType;
}
public void setTaskType(TaskType taskType) {
this.taskType = taskType;
}
public Long getAssetRoleId() {
return assetRoleId;
}
public void setAssetRoleId(Long assetRoleId) {
this.assetRoleId = assetRoleId;
}
public Role getAssetRole() {
return assetRole;
}
public void setAssetRole(Role assetRole) {
this.assetRole = assetRole;
}
public Long getDefaultAssetId() {
return defaultAssetId;
}
public void setDefaultAssetId(Long defaultAssetId) {
this.defaultAssetId = defaultAssetId;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
I tried saving a taskTypeAssetRole with a new defaultAssedId without setting defaultAsset and I expected the defaultAssedId for that entry in the database to be updated.
What ended up happening was defaultAssetId didn't change although everything else in the entry did update successfully and there were no errors.
Your mapping is inherently broken. The column defaultassetiId is mapped to two different values: the field defaultAssetId and to the id of defaultAsset.
You should remove the defaultAssetId because this construct might break on any update of your JPA provider.
You can use references instead of full entities to set the reference values without loading entities from the database. See https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html#getReferenceById-ID-
If you don't follow this advice you should remove updatable=false if you want to update a field.
Im getting very strange error when I call save on a JpaRepository.
The code seems trivial so i can only think its something to do with configuration.
Basically I call a findBy method on the repository, this returns a list of dao objects exactly as expected, I go through this list setting a timestamp then calling save() on each dao, as soon as the first save is called the log is filled with hundreds of identical select statements, selecting on the dao I'm just trying to save until eventually there is a stack overflow.
What could cause this ???
(note originally I called saveAll() on the list of dao objects - this, unsurprisingly has the same error )
public void triggerDeletion() {
ZonedDateTime expiryDate = ZonedDateTime.now().minus(daysAfterExpiry);
// Get list of conversations to delete
List<ConversationDao> conversationDaoList = conversationDatabaseService.retrieveExpiredConversations(expiryDate);
// Mark each conversation as deleted by setting its deletion timestamp to now.
conversationDaoList.stream().forEach(conversation->delete(conversation));
}
public void delete(ConversationDao conversationDao){
conversationDao.setDeletionTimestamp(new Timestamp(System.currentTimeMillis()));
conversationDatabaseService.save( conversationDao ); <------ This generates 100s of select statements.
}
...
// ConversationDatabaseService Interface
////////////////////////////////////////
public interface ConversationDatabaseService {
void save(ConversationDao conversationDao);
}
...
// Conversation DatabaseService Class
/////////////////////////////////////
#Service
public class ConversationDatabaseServiceImpl implements ConversationDatabaseService {
private final ConversationRepository conversationRepository;
public void save(ConversationDao conversationDao) {
conversationRepository.saveAndFlush(conversationDao); // Just save has also been tried.
}
}
...
// ConversationRepository interface
///////////////////////////////////
public interface ConversationRepository extends JpaRepository<ConversationDao, String> {
List<ConversationDao> findByExpiryDateLessThanAndDeletionTimestampIsNull(Timestamp expiryDate);
}
...
// ConversationDao
//////////////////////////////////
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;
#Entity
#Table(name = "DOCX_CONVERSATION")
public class ConversationDao {
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2",
strategy = "uuid2")
#Column(name = "CONVERSATION_ID",
columnDefinition = "char")
private String conversationId;
#Column(name = "PROCESS_CODE")
private String processCode;
#Column(name = "PROFILE_ID",
columnDefinition = "char")
private String profileId;
#Column(name = "REMINDER_EMAIL_SENT",
columnDefinition = "char")
private String reminderEmailSent;
#Column(name = "EXPIRY_DATE")
private Date expiryDate;
#Column(name = "DELETION_TIMESTAMP")
private Timestamp deletionTimestamp;
#Column(name = "LAST_LOGIN_TIMESTAMP")
private Timestamp lastLoginTimestamp;
#Column(name = "CREATED_USER_ID",
columnDefinition = "char")
private String colleagueId;
#Column(name = "CREATED_TIMESTAMP",
updatable = false)
#CreationTimestamp
private Timestamp createdTimestamp;
#Column(name = "LAST_UPDATED_USER_ID",
columnDefinition = "char")
private String lastUpdatedUserId;
#Column(name = "LAST_UPDATED_TIMESTAMP")
#UpdateTimestamp
private Timestamp lastUpdatedTimestamp;
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<MessageDetailDao> messageDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "fileDetailId.conversation",
cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<ParameterDao> parameterDaoSet = new HashSet<>();
#OneToMany(mappedBy = "conversation",
cascade = CascadeType.ALL)
private Set<NotificationDao> notificationDaoSet = new HashSet<>();
public ConversationDao() {
}
public ConversationDao(String processCode, Date expiryDate,
String colleagueId, String lastUpdatedUserId) {
this.processCode = processCode;
this.reminderEmailSent = "N";
this.expiryDate = expiryDate;
this.colleagueId = colleagueId;
this.lastUpdatedUserId = lastUpdatedUserId;
}
public String getConversationId() {
return conversationId;
}
public void setConversationId(String conversationId) {
this.conversationId = conversationId;
}
public String getProcessCode() {
return processCode;
}
public void setProcessCode(String processCode) {
this.processCode = processCode;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public String getReminderEmailSent() {
return reminderEmailSent;
}
public void setReminderEmailSent(String reminderEmailSent) {
this.reminderEmailSent = reminderEmailSent;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
public Timestamp getDeletionTimestamp() {
return deletionTimestamp;
}
public void setDeletionTimestamp(Timestamp deletionTimestamp) {
this.deletionTimestamp = deletionTimestamp;
}
public Timestamp getLastLoginTimestamp() {
return lastLoginTimestamp;
}
public void setLastLoginTimestamp(Timestamp lastLoginTimestamp) {
this.lastLoginTimestamp = lastLoginTimestamp;
}
public String getColleagueId() {
return colleagueId.trim();
}
public void setColleagueId(String colleagueId) {
this.colleagueId = colleagueId;
}
public Timestamp getCreatedTimestamp() {
return createdTimestamp;
}
public void setCreatedTimestamp(Timestamp createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}
public String getLastUpdatedUserId() {
return lastUpdatedUserId;
}
public void setLastUpdatedUserId(String lastUpdatedUserId) {
this.lastUpdatedUserId = lastUpdatedUserId;
}
public Timestamp getLastUpdatedTimestamp() {
return lastUpdatedTimestamp;
}
public void setLastUpdatedTimestamp(Timestamp lastUpdatedTimestamp) {
this.lastUpdatedTimestamp = lastUpdatedTimestamp;
}
public void addMessageDetailDao(MessageDetailDao messageDetailDao) {
messageDetailDaoSet.add(messageDetailDao);
messageDetailDao.setConversation(this);
}
public Set<MessageDetailDao> getMessageDetailDao() {
return messageDetailDaoSet;
}
public void addFileDetailDao(FileDetailDao fileDetailDao) {
fileDetailDaoSet.add(fileDetailDao);
fileDetailDao.getId().setConversation(this);
}
public Set<FileDetailDao> getFileDetailDao() {
return fileDetailDaoSet;
}
public void addParameterDao(ParameterDao parameterDao) {
parameterDaoSet.add(parameterDao);
parameterDao.setConversation(this);
}
public Set<ParameterDao> getParameterDao() {
return parameterDaoSet;
}
public void addNotificationDao(NotificationDao notificationDao) {
notificationDaoSet.add(notificationDao);
notificationDao.setConversation(this);
}
public Set<NotificationDao> getNotificationDao() {
return notificationDaoSet;
}
}
}
This generates these same select statements 100s of times before blowing the stack :-
1TS="20190411.075004.028" 4MSG="binding parameter [1] as [VARCHAR] - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicBinder"
1TS="20190411.075004.065" 4MSG="extracted value ([convers16_10_0_] : [VARCHAR]) - [6df49d6f-216b-460d-9282-2d25c098f9fe]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.069" 4MSG="extracted value ([file_met1_10_0_] : [VARCHAR]) - [4E90FD20-FC59-41B8-BF8E-88B7D682A87C]" 1EVC="TRACE" 2CLS="BasicExtractor"
1TS="20190411.075004.074" 4MSG="select conversati0_.conversation_id as conversa1_5_1_, conversati0_.created_user_id as created_2_5_1_, conversati0_.created_timestamp as created_3_5_1_, conversati0_.deletion_timestamp as deletion4_5_1_, conversati0_.expiry_date as expiry_d5_5_1_, conversati0_.last_login_timestamp as last_log6_5_1_, conversati0_.last_updated_timestamp as last_upd7_5_1_, conversati0_.last_updated_user_id as last_upd8_5_1_, conversati0_.process_code as process_9_5_1_, conversati0_.profile_id as profile10_5_1_, conversati0_.reminder_email_sent as reminde11_5_1_, filedetail1_.conversation_id as convers16_10_3_, filedetail1_.file_metadata_id as file_met1_10_3_, filedetail1_.conversation_id as convers16_10_0_, filedetail1_.file_metadata_id as file_met1_10_0_, filedetail1_.application_id as applicat2_10_0_, filedetail1_.case_id as case_id3_10_0_, filedetail1_.created_user_id as created_4_10_0_, filedetail1_.content_type as content_5_10_0_, filedetail1_.created_by as created_6_10_0_, filedetail1_.created_timestamp as created_7_10_0_, filedetail1_.document_code as document8_10_0_, filedetail1_.document_owner as document9_10_0_, filedetail1_.document_repository_state as documen10_10_0_, filedetail1_.file_name as file_na11_10_0_, filedetail1_.file_size_bytes as file_si12_10_0_, filedetail1_.file_state as file_st13_10_0_, filedetail1_.file_version as file_ve14_10_0_, filedetail1_.updated_by as updated15_10_0_ from docx_conversation conversati0_ left outer join docx_file_detail filedetail1_ on conversati0_.conversation_id=filedetail1_.conversation_id where conversati0_.conversation_id=?" 1EVC="DEBUG" 2CLS="SQL"
What is going on ??
Some more information, the cause is definitely connected to this part of the dao :-
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.ALL)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
The FileDetailDao contains an embedded reference to a FileDetailId
#EmbeddedId
private FileDetailId fileDetailId;
And this FileDetailId contains a reference to the conversationId of the join :-
#Embeddable
public class FileDetailId implements Serializable {
#Column(name = "FILE_METADATA_ID", columnDefinition = "char")
private String fileMetadataId;
#ManyToOne
#JoinColumn(name = "CONVERSATION_ID")
private ConversationDao conversation;
//etc
}
Im not sure why but if I change the cascade type to REMOVE it works ok....
#OneToMany(mappedBy = "fileDetailId.conversation",cascade = CascadeType.REMOVE)
private Set<FileDetailDao> fileDetailDaoSet = new HashSet<>();
I'm working in a project and I'm looking to add data to the database, to two join tables.
My parent:
package entity;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the artiste database table.
*
*/
#Entity
#NamedQuery(name="Artiste.findAll", query="SELECT a FROM Artiste a")
public class Artiste implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_artiste")
private int idArtiste;
#Column(name="a_category")
private String aCategory;
#Column(name="a_name")
private String aName;
private String date;
//bi-directional many-to-one association to Seat
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
public Artiste() {
}
public int getIdArtiste() {
return this.idArtiste;
}
public void setIdArtiste(int idArtiste) {
this.idArtiste = idArtiste;
}
public String getACategory() {
return this.aCategory;
}
public void setACategory(String aCategory) {
this.aCategory = aCategory;
}
public String getAName() {
return this.aName;
}
public void setAName(String aName) {
this.aName = aName;
}
public String getDate() {
return this.date;
}
public void setDate(String date) {
this.date = date;
}
public Seat getSeat() {
return this.seat;
}
public void setSeat(Seat seat) {
this.seat = seat;
}
}
My child:
package entity;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the seat database table.
*
*/
#Entity
#NamedQuery(name="Seat.findAll", query="SELECT s FROM Seat s")
public class Seat implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id_seat")
private int idSeat;
private String seat_CA;
private String seat_CB;
private String seat_CC;
private String seat_CD;
//bi-directional many-to-one association to Artiste
#OneToMany(mappedBy="seat")
private List<Artiste> artistes;
public Seat() {
}
public int getIdSeat() {
return this.idSeat;
}
public void setIdSeat(int idSeat) {
this.idSeat = idSeat;
}
public String getSeat_CA() {
return this.seat_CA;
}
public void setSeat_CA(String seat_CA) {
this.seat_CA = seat_CA;
}
public String getSeat_CB() {
return this.seat_CB;
}
public void setSeat_CB(String seat_CB) {
this.seat_CB = seat_CB;
}
public String getSeat_CC() {
return this.seat_CC;
}
public void setSeat_CC(String seat_CC) {
this.seat_CC = seat_CC;
}
public String getSeat_CD() {
return this.seat_CD;
}
public void setSeat_CD(String seat_CD) {
this.seat_CD = seat_CD;
}
public List<Artiste> getArtistes() {
return this.artistes;
}
public void setArtistes(List<Artiste> artistes) {
this.artistes = artistes;
}
public Artiste addArtiste(Artiste artiste) {
getArtistes().add(artiste);
artiste.setSeat(this);
return artiste;
}
public Artiste removeArtiste(Artiste artiste) {
getArtistes().remove(artiste);
artiste.setSeat(null);
return artiste;
}
}
My client:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setIdArtiste(b.getIdSeat());
seatFacade.create(b);
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
artisteFacade.create(a);
And I create the FACADE for each one.
Now I can add data but i need also the program add the FOREIGN KEY.
You don't need to get the foreign key, JPA is do every thing, so you should just make it in the right way, so you entities should look like this:
Artiste Entity
#ManyToOne
#JoinColumn(name="id_seat")
private Seat seat;
Seat Entity
#OneToMany(mappedBy="seat", cascade = CascadeType.ALL)
private List<Artiste> artistes = new ArrayList<>();
Your code should look like this:
Artiste a= new Artiste();
Seat b = new Seat();
b.setSeat_CA(request.getParameter("w"));
b.setSeat_CB(request.getParameter("x"));
b.setSeat_CD(request.getParameter("y"));
b.setSeat_CC(request.getParameter("z"));
a.setAName(request.getParameter("a_name"));
a.setACategory(request.getParameter("a_category"));
a.setDate(request.getParameter("date"));
//add this the Article to the list of Seat like this.
b.getArtistes().add(a);
//a.setIdArtiste(b.getIdSeat()); you don't need this
//artisteFacade.create(a); you dont need this also
//set the Seal to your article
a.setSeat(b);
seatFacade.create(b);
So when you persist the Seat the list of articles will persist automaticlly.
This will help you.
You can learn more here : JPA #ManyToOne with CascadeType.ALL
The table in the database (Oracle 11g) is like this:
Name: LOG_ALIM_MAIL
Columns : ID_LOG RAW (automatically generated by SYS_GUID() in trigger), ALIMENTATION Number(9), DATE_LOG Date
PK: ID_LOG
FK: ALIMENTATION References ALIMENTATION.ID_ALIMENTATION (Number(9))
LOG_ALIM_MAIL class:
#Entity
public class LogAlimMail implements Serializable {
private static final long serialVersionUID = 2243374060845658640L;
#Id
private Long idLog;
private Date dateLog;
private Alimentation alimentation;
public LogAlimMail() {
}
public Long getIdLog() {
return idLog;
}
public void setIdLog(Long idLog) {
this.idLog = idLog;
}
public Date getDateLog() {
return dateLog;
}
public void setDateLog(Date dateLog) {
this.dateLog = dateLog;
}
#ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
public Alimentation getAlimentation() {
return alimentation;
}
public void setAlimentation(Alimentation alimentation) {
this.alimentation = alimentation;
}
}
Alimentation class:
#Entity
public class Alimentation implements Serializable {
private static final long serialVersionUID = 5790314265385194058L;
private Long idAlimentation;
private Integer etat;
public Alimentation() {
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "my_alimentation_seq_gen")
#SequenceGenerator(name = "my_alimentation_seq_gen", sequenceName = "SEQ_ID_ALIMENTATION")
public Long getIdAlimentation() {
return idAlimentation;
}
public Integer getEtat() {
return etat;
}
public void setEtat(Integer etat) {
this.etat = etat;
}
public void setIdAlimentation(Long idAlimentation) {
this.idAlimentation = idAlimentation;
}
}
I've got two questions:
I'm trying to execute the following select query:
public List<LogAlimMail> getAllByIdAlim(Long idAlim) {
String request = "select a from LogAlimMail a where a.alimentation.idAlimentation = " + idAlim;
Query query = this.getEntityManager().createQuery(request);
return query.getResultList();
}
I get the Exception :
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: idAlimentation of: administration.LogAlimMail [select a from administration.LogAlimMail a where a.alimentation.idAlimentation = 1]
I can't do the right JPA mapping between idLog (Long) and ID_LOG (RAW generated by SYS_GUID()).
Thanks
Is idAlim a number? If not, you should use idAlimentation = '" + idAlim + "'";
Or better, use bound variables:
idAlimentation = :idAlim";
query.setString("idAlim", idAlim);
How can I write the following relationship in JPA. I have 6 tables: Products, Features, Functions, Tasks, Permissions and Users. I need to be able to create a Product object model that contains a list of Features. Each Feature object model in the list will contain a list of Functions and each Function will contain a list of Tasks. I have no issue building each one of these entities and then relating them together but the problem comes in when I need to filter each entity by its relationship to the Permission table. I'm not sure this can be done. When I map the Permissions entity to each other entity, I seem to get a many-to-many join and too many values are returned. Any insight would be great.
Products
prod_id
user_id
Features
prod_id
feature_id
Functions
prod_id
feature_id
function_id
Tasks
prod_id
feature_id
function_id
task_id
Permissions
prod_id
feature_id
function_id
task_id
user_id
User
user_id
Here is my Permission entity class:
import java.io.Serializable;
import javax.persistence.*;
import static javax.persistence.CascadeType.ALL;
import java.math.BigDecimal;
#IdClass(menu.entity.PermissionKey.class)
#Entity
#Table(name="PERMISSIONS")
#NamedQuery(name = "findPermissionsByUserId",query = "SELECT p FROM Permission p WHERE p.userId = :userId")
public class Permission implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="AUTH", length=1)
private String auth;
#Column(name="PERM_DESC", length=80)
private String permDesc;
#Id
#Column(name="COMPANY",
nullable = false,
insertable = false,
updatable = false,
length=2)
private String company;
#Id
#Column(name="USER_ID",
nullable = false,
insertable = false,
updatable = false,
length=30)
private String userId;
#Id
#Column(name="PROD_ID", precision=22)
private BigDecimal prodId;
#Id
#Column(name="FEATURE", precision=22)
private BigDecimal feature;
#Id
#Column(name="FUNC", precision=22)
private BigDecimal func;
#Id
#Column(name="TASK", precision=22)
private BigDecimal task;
//uni-directional one-to-one association to Product
#OneToOne(cascade=ALL, mappedBy="permission")
private Product productObj;
#OneToOne(cascade=ALL, mappedBy="permission")
private Feature featureObj;
#OneToOne(cascade=ALL, mappedBy="permission")
private Function functionObj;
#OneToOne(cascade=ALL, mappedBy="permission")
private Task taskObj;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="USER_ID", referencedColumnName="USER_ID"),
#JoinColumn(name="COMPANY", referencedColumnName="COMPANY")
})
private User user;
public Permission() {
}
public String getAuth() {
return this.auth;
}
public void setAuth(String auth) {
this.auth = auth;
}
public String getCompany() {
return this.company;
}
public void setCompany(String company) {
this.company = company;
}
public String getPermDesc() {
return this.permDesc;
}
public void setPermDesc(String permDesc) {
this.permDesc = permDesc;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public BigDecimal getProdId() {
return prodId;
}
public void setProdId(BigDecimal prodId) {
this.prodId = prodId;
}
public BigDecimal getFeature() {
return this.feature;
}
public void setFeature(BigDecimal feature) {
this.feature = feature;
}
public BigDecimal getFunc() {
return func;
}
public void setFunc(BigDecimal func) {
this.func = func;
}
public BigDecimal getTask() {
return task;
}
public void setTask(BigDecimal task) {
this.task = task;
}
public Product getProductObj() {
return this.productObj;
}
public void setProductObj(Product productObj) {
this.productObj = productObj;
}
public Feature getFeatureObj() {
return this.featureObj;
}
public void setFeatureObj(Feature featureObj) {
this.featureObj = featureObj;
}
public Function getFunctionObj() {
return this.functionObj;
}
public void setFunctionObj(Function functionObj) {
this.functionObj = functionObj;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public Task getTaskObj() {
return this.taskObj;
}
public void setTaskObj(Task taskObj) {
this.taskObj = taskObj;
}
}