Spring data with #PrimaryKeyJoinColumn throws Exception - java

I use Spring data jpa and I have two Entities that have inheritance relationship.
Here is the parent.
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#Table(name = "creditcardinfo")
#DiscriminatorColumn
public class CreditCardInfo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="credit_card_info_id")
private int creditCardInfoId;
And here is the child
#Entity
#DiscriminatorValue("tappay")
#Table(name = "tappaycardinfo")
#PrimaryKeyJoinColumn(name = "credit_card_info_id",referencedColumnName = "credit_card_info_id")
public class TappayCardInfo extends CreditCardInfo implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "card_token")
private String cardToken;
#Column(name = "card_key")
private String cardKey;
And I use JpaRepository to CRUD. Here's my repository.
public interface TappayCardInfoDAO extends JpaRepository<TappayCardInfo, Integer>
I always got an Exception when I saved my TappayCardInfo.
#Inject private TappayCardInfoDAO tappayCardInfoDAO;
...
tappayCardInfoDAO.save(cardInfo);
Here's error message.
Caused by: java.lang.IllegalArgumentException: The entity must have one and only one property with id annotation, class name: base.model.TappayCardInfo

Related

How to add fields in audit table using Envers in Spring Boot

Good morning, how can I add fields in my audit table?
I need to audit some tables, but I need to get the user who did the operation. My entity who will be audited is:
#Entity
#Table(name ="TableName")
#Audited
#AuditTable("TableNameAuditedLog")
public class MyEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "myId")
private Long id;
#Column(name = "myName")
private String name;
}
Looking the docs, I saw an example a custom class to be my audit and a listener, so I made like this:
#Data
#RevisionEntity(AuditListener.class)
#MappedSuperclass
public class Audit {
#Id
#GeneratedValue
#RevisionNumber
private Long id;
#RevisionTimestamp
private Long timestamp;
#Column(name = "user")
private String user;
}
public class AuditListener implements RevisionListener {
#Override
public void newRevision(Object revisionEntity) {
Audit audit = (Audit) revisionEntity;
audit.setUsuario("user");
}
}
I've tried to extends my Audit class in my Entity class, but I'd trouble with JPA, the trouble is:
Caused by: org.hibernate.MappingException: Unable to find column with logical name: myId in org.hibernate.mapping.Table(TableNameAuditedLog) and its related supertables and secondary tables
How can I do this?
Thank you all.
Remove the MappedSuperClass from your Audit class. You could also have Audit extend DefaultRevisionEntity. All you would have in Audit class is your custom field.
#Column(name = "user")
private String user;
A custom audit revision entity:
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#RevisionEntity(UserRevisionListener.class)
public class AuditRevisionEntity extends DefaultTrackingModifiedEntitiesRevisionEntity {
private static final long serialVersionUID = 1L;
private Long userId;
#Column(length = 100, nullable = false)
private String initiator;
}
And revision listener
public class UserRevisionListener implements RevisionListener {
private static final String SYSTEM_USER = "System";
private transient final SecurityUtils securityUtils;
public UserRevisionListener(final SecurityUtils securityUtils) {
this.securityUtils = securityUtils;
}
#Override
public void newRevision(Object revisionEntity) {
final AuditRevisionEntity are = (AuditRevisionEntity) revisionEntity;
securityUtils.getPrincipal().ifPresentOrElse((appPrincipal) -> {
are.setUserId(appPrincipal.getUserId());
are.setInitiator(appPrincipal.getDisplayName());
}, () -> are.setInitiator(SYSTEM_USER));
}
}
In my case I am getting the current principal(I am using a custom principal that has the extra fields) using a SecurityUtils helper and setting the AuditRevisionEntity as needed. Some changes are made by Quartz jobs so there is no principal in which case only the initiator is set.

Java JPA - Table per class inheritance - Id collision

I have one Parent class with ID field, and two Child classes. I have applied TABLE PER CLASS inheritance.
Some Rows in these two tables have the same identifiers. (The same Id)
When findAll() of the JpaRepository is called I have org.hibernate.PropertyAccessException
What I can to do to resolve the conflict? I can not to change IDs in these tables, because they have a lot of dependencies and foreign key constraints.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Parent implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#TableGenerator(name = "content_id_generator",
table = "generic_sequences",
pkColumnName = "sequence_name",
valueColumnName = "sequence_value",
pkColumnValue= "content_seq",
allocationSize = 20)
#GeneratedValue(strategy = GenerationType.TABLE, generator = "content_id_generator")
#Column(updatable = false)
private Long id;
#Column(length = 250, nullable = false)
#NotNull
#Size(min = 1, max = 250)
private String title;
...
There are tho child classes Child1 and Child2 extends Parent.
There is another inheritance that dependent from Content.
#Entity
#Table(name = "text_id_changed")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "type")
public abstract class DependentCalss implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(updatable = false)
private Long id;
...
DependentCalss has two child classes DependentCalssChild1 and DependentCalssChild2.
#Entity
#DiscriminatorValue("DependentCalssChild1")
public class DependentCalssChild1 extends DependentCalss {
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name = "child_1_id")
private Child1 child1;
...
AND
#Entity
#DiscriminatorValue("DependentCalssChild2")
public class DependentCalssChild2 extends DependentCalss {
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name = "child_2_id")
private Child2 child2;
...
And jpaRepository
#Repository
public interface DependentCalssRepository extends JpaRepository<DependentCalss, Long> {
}
When I call findAll() of DependentCalssRepository I catch org.hibernate.PropertyAccessException that field can not be set etc.
It happens when Child1 and Child2 have the same ID in separate tables.
What can I do to resolve it? I can not change id in tables because of great number dependencies and constraints. Thanks!

Will the findAll function of Spring Data JPA repository work if the entites are related as many to one or one to one or any such association?

Here is how the entity class looks like
#Entity
public class IndustryCode {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String industryName;
#OneToMany(mappedBy="industryCode")
private Set<CarrierCodes> industryCodes;
#Entity
public class TechCode {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String techName;
#OneToMany(mappedBy="techCode")
private Set<CarrierCodes> techCodes;
#Entity
public class CarrierCodes {
#EmbeddedId
private CarrierCodesId id = new CarrierCodesId();
#ManyToOne
#MapsId("techCodeId")
private TechCode techCode;
#ManyToOne
#MapsId("industryCodeId")
private IndustryCode industryCode;
#SuppressWarnings("serial")
#Embeddable
public class CarrierCodesId implements Serializable {
private Long industryCodeId;
private Long techCodeId;
#Entity
public class Register {
#Id
private Long mobileNumber;
#ManyToOne
// optional but nice to have consistent names
#JoinColumns({
#JoinColumn(name="industryCode_id", referencedColumnName="industryCode_id"),
#JoinColumn(name="techCode_id", referencedColumnName="techCode_id")
)
private CarrierCodes carrierCodes;
}
public class RegisterRepository extends JPARepository<Register,mobileNumber>{
}
My question is if I run findAll on Register table will I get the data for other related tables as well?
I mean using findAll(), will I get a List from which I can take Register obj and use .getCarrierCode().getIndustryCode().getIndustryName() to get industry name corresponding to carrierCode value in Register table

java - Hibernate Search - Unable to perform work. Entity Class is not #Indexed nor hosts #ContainedIn

I have a Spring JPA project with 3 entities: Author, Book and Category.
I want to use Hibernate Search for indexes.
Author class is #Indexed; Book class contains a Category field annotated with #ContainedIn; Category is a very simple class.
CLASS Author
#Entity
#Table
#Indexed
public class Author extends ConcreteEntity {
private static final long serialVersionUID = 1L;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#IndexedEmbedded
private List<Book> books = new ArrayList<>();
}
CLASS Book
#Entity
#Table
public class Book extends ConcreteEntity {
private static final long serialVersionUID = 1L;
#ContainedIn
private Category category;
}
CLASS Category
#Entity
#Table
public class Category extends ConceptEntity {
private static final long serialVersionUID = 1L;
}
CLASS ConcreteEntity and ConceptEntity are similars:
#MappedSuperclass
public abstract class ConcreteEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String name;
#Column
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String value;
}
#MappedSuperclass
public abstract class ConceptEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String name;
#Column
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String value;
}
I've got this exception while saving a resource using Hibernate Search.
org.hibernate.search.exception.SearchException: Unable to perform work. Entity Class is not #Indexed nor hosts #ContainedIn: class test.hibernate.search.Category
I don't understand how to solve this issue.
Thanks
Book is not configured correctly. You tell Hibernate Search that Book is included in the Category index (via your #ContainedIn annotation on the category field) but your Category entity is neither marked with #Indexed nor linked to another index via #ContainedIn.
Hibernate Search is just telling you that your configuration doesn't make much sense.
Considering your model, I'm pretty sure you wanted to mark category with #IndexedEmbedded instead.

createAlias/createCriteria hibernate INNER_JOIN

I am having two tables Parent and Child. The query I want to use in Hibernate Criteria
SELECT tcr.*
FROM case_reminders tcr
INNER JOIN case_reminder_opr tco ON tcr.case_id = tco.case_id
WHERE tcr.case_status = 'OPN'
AND tco.operator_id = 111;
I have written the criteria as
Criteria ctr = getSession().createCriteria(CaseReminderOpr.class).add(Restrictions.eq("pk.oprOperatorId", operatorId));
ctr.createCriteria("pk.crmCaseId", "CR", Criteria.INNER_JOIN).add(Restrictions.eq("CR.caseStatus", STATUS.OPEN.getValue()));
List<CaseReminderOpr> oprList = ctr.list();
tried with createAlias as well but I am getting error as
ORA-00904: "CR1_"."CASE_STATUS": invalid identifier
Classes of CaseReminders(Parent) and CaseReminderOpr(Child) as follows.
#Entity
#Table(name = "CASE_REMINDERS")
public class CaseReminders implements Serializable {
#Id
#Column(name = "CASE_ID")
private Long caseId;
#Column(name = "CASE_STATUS")
private String caseStatus;
}
#Entity
#Table(name="CASE_REMINDER_OPR")
public class CaseReminderOpr implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private CaseReminderOprPK pk;
}
#Embeddable
public class CaseReminderOprPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#ManyToOne
#JoinColumn(name = "CASE_ID")
private CaseReminders crmCaseId;
#Column(name="OPERATOR_ID")
private Long operatorId;
}
Please help me with the inner_join query, appreciate your help again.
The change would be as below then it works. I have realized this later.
Make the Joincolumn as insertable=false,updatable=false in main entity class.
#Entity
#Table(name="CASE_REMINDER_OPR")
public class CaseReminderOpr implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private CaseReminderOprPK pk;
#ManyToOne
#JoinColumn(name = "CASE_ID", insertable=false, updatable=false)
private CaseReminders caseRem;
}
Now the query should work as expected.
Criteria ctr = getSession().createCriteria(CaseReminderOpr.class, "CRO").add(Restrictions.eq("pk.oprOperatorId", operatorId));
ctr.createCriteria("CRO.caseRem", "CR", Criteria.INNER_JOIN).add(Restrictions.eq("CR.caseStatus", STATUS.OPEN.getValue()));
List<CaseReminderOpr> oprList = ctr.list();
Hopefully I am clear in explaining.

Categories