Can't save entity Embeddable Id - java

I have EcranChamp entity
#Entity
#IdClass(EcranChampId.class)
public class EcranChamp {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ecran")
Ecran ecran;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "champ")
Champ champ;
...
And EcranChampId
#Embeddable
public class EcranChampId implements Serializable {
private Champ champ;
private Ecran ecran;
...
Every time i am trying to save an EcranChamp element i have this following error
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to convert request element: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found

Try something like this:
#Entity
#Table(name = "<entity name>")
public class EcranChamp {
#EmbeddedId
#AttributeOverrides({ #AttributeOverride(name = "id_ecran", column = #Column(name =
"<column name>", nullable = false)),
#AttributeOverride(name = "id_champ", column = #Column(name = "<column name>", nullable = false)) })
EcranChampId id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_ecran")
Ecran ecran;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_champ")
Champ champ;
//getters & setters
}
#Embeddable
public class EcranChampId implements Serializable {
#Column(name = "id_champ", nullable = false)
private Long id_champ;
#Column(name = "id_ecran", nullable = false)
private Long id_ecran;
//getters & setters
}

You shoud use #EmbeddedId annotation.
Please, change your EcranChampId class to this:
#Embeddable
public class EcranChampId implements Serializable {
#ManyToOne
private Champ champ;
#ManyToOne
private Ecran ecran;
//getters and setters
}
And change your EcranChamp class to this:
#Entity
#Table(name = "champ_has_ecran_table_name")
#AssociationOverrides({
#AssociationOverride(name = "pk.champ", joinColumns = #JoinColumn(name = "champ_id"))
#AssociationOverride(name = "pk.ecran", joinColumns = #JoinColumn(name = "ecran_id"))
})
public class EcranChamp {
#EmbeddedId
private EcranChampId pk;
public EcranChamp() {
pk = new EcranChampId();
}
public EcranChampId getPk() {
return pk;
}
public void setPk(EcranChampId pk) {
this.pk = pk;
}
#Transient
public Champ getChamp() {
return pk.getChamp();
}
public void setChamp(Champ champ) {
pk.setChamp(champ);
}
#Transient
public Ecran getEcran() {
return pk.getEcran();
}
public void setChamp(Ecran ecran) {
pk.setEcran(ecran);
}
}
And use it like this:
public class Champ {
#OneToMany(mappedBy = "pk.champ")
private Collection<EcranChamp> ecranChamps;
//getters and setters
}
Also, if EcranChamp or EcranChampId has no other fields i will recommend you to use #ManyToMany annotation instead EcranChamp class like this:
public class Champ {
#ManyToMany
#JoinTable(
name = "champ_has_ecran_table_name",
joinColumns = #JoinColumn(name = "champ_id", referencedColumnName = "id", nullable = false),
inverseJoinColumns = #JoinColumn(name = "ecran_id", referencedColumnName = "id", nullable = false)
)
private Collection<Ecran> ecrans;
//getters and setters
}

Related

Hibernate find by enum

I have 2 classes with One-to-Many relationship
#javax.persistence.Entity
#TypeDef(name = "InquiryIdType", typeClass = InquiryIdType.class)
public class Inquiry implements Entity
{
#javax.persistence.Id
#Type(type = "InquiryIdType")
#Column(name = "id", columnDefinition = DB_ENTITY_ID_TYPE)
private InquiryId id;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "conference_session_id", nullable = false)
private ConferenceSession conferenceSession;
#Column(name = "state", nullable = false)
#Enumerated(EnumType.STRING)
private QuizStateType quizStateType;
and
public enum QuizStateType
{
IN_PROGRESS(0),
FINISHED(1),
NOT_STARTED(2),
DELETED(3);
public int value;
QuizStateType(int value)
{
this.value = value;
}
}
I need to find "Inquiry" by the Conference session Id_id and QuizStateType (is Deleted). I try, but swears at the context.
nested exception is
org.springframework.data.mapping.PropertyReferenceException: No
property is found for type QuizStateType! Traversed path:
Inquiry.quizStateType.
public interface InquiryRepository extends JpaRepository<Inquiry, UUID>
{
List<Inquiry> findByConferenceSession_idAndQuizStateTypeIs_DELETED (UUID conferenceSessionId);
}

Issue on hibernate oneToMany with spring boot and postgres

I have an issue with hibernate and postgres using spring boot.
When I run the application I see in postgres logs these errors(without any data bootstrap):
2021-06-25 13:55:31.057 UTC [81] ERROR: constraint "uk_j1xiaxeat9b5r1qs27ei0t2a6" of
relation "process_template_base_environmental_impact" does not exist
2021-06-25 13:55:31.057 UTC [81] STATEMENT: alter table
process_template_base_environmental_impact drop constraint
UK_j1xiaxeat9b5r1qs27ei0t2a6
2021-06-25 13:55:31.062 UTC [81] ERROR: constraint "uk_9568qjc94suvuskoi9o2li3er" of
relation "process_template_elementary_flow_template" does not exist
2021-06-25 13:55:31.062 UTC [81] STATEMENT: alter table
process_template_elementary_flow_template drop constraint
UK_9568qjc94suvuskoi9o2li3er
2021-06-25 13:55:31.064 UTC [81] ERROR: constraint "uk_dy1ej2j9qxeoq6ca641tpfxr5" of
relation "process_template_flow_template" does not exist
2021-06-25 13:55:31.064 UTC [81] STATEMENT: alter table
process_template_flow_template drop constraint UK_dy1ej2j9qxeoq6ca641tpfxr5
I have an entity called ProcessTemplate with ProcessTemplateId as compositeKey, and 3 cascades on ElementaryFlowTemplate, BaseEnvironmentalImpact, and FlowTemplate.
ProcessTemplate:
#Data
#Entity
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Table(name = "process_template")
public class ProcessTemplate {
#EmbeddedId
#EqualsAndHashCode.Include
private ProcessTemplateId id;
#ManyToOne
#JoinColumn(name = "fk_process_base", referencedColumnName = "id")
private ProcessBase processBase;
#ManyToOne
#JoinColumn(name = "fk_reference_flow_base", referencedColumnName = "id")
private FlowBase referenceProduct;
#OneToMany(cascade = CascadeType.ALL)
private Set<BaseEnvironmentalImpact> baseEnvironmentalImpacts;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("impactsContribute DESC" )
private Set<FlowTemplate> flowsTemplate;
#OneToMany(cascade = CascadeType.ALL)
#OrderBy("impactsContribute DESC" )
private Set<ElementaryFlowTemplate> elementaryFlowsTemplate;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
}
ProcessTemplateId:
#Embeddable
public class ProcessTemplateId implements Serializable {
#Column(name = "process_base_id")
private UUID processBaseId;
#Column(name = "reference_product_id")
private UUID referenceProductId;
public ProcessTemplateId() {
}
public ProcessTemplateId(UUID processBaseId, UUID referenceProductId) {
this.processBaseId = processBaseId;
this.referenceProductId = referenceProductId;
}
public UUID getProcessBaseId() {
return processBaseId;
}
public UUID getReferenceProductId() {
return referenceProductId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProcessTemplateId)) return false;
ProcessTemplateId that = (ProcessTemplateId) o;
return Objects.equals(getProcessBaseId(), that.getProcessBaseId()) &&
Objects.equals(getReferenceProductId(), that.getReferenceProductId());
}
#Override
public int hashCode() {
return Objects.hash(getProcessBaseId(), getReferenceProductId());
}
}
AbstractFlowTemplate:
#Data
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractFlowTemplate {
#Id
#EqualsAndHashCode.Include
private String id;
#Enumerated(EnumType.STRING)
private FlowType flowType;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
}
ElementaryFlowTemplate:
#Data
#Entity
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
#Table(name = "elementary_flow_template")
public class ElementaryFlowTemplate extends AbstractFlowTemplate {
#ManyToOne
#JoinColumn(name = "fk_elementary_flow_base", referencedColumnName = "id")
private ElementaryFlowBase elementaryFlowBase;
}
FlowTemplate (linkedProcessTemplate is not the bidirectional relation to ProcessTemplate but another unidirectional relation, because each flowTemplate had a link to another ProcessTemplate):
#Data
#Entity
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
#Table(name = "flow_template")
public class FlowTemplate extends AbstractFlowTemplate {
#ManyToOne
#JoinColumn(name = "fk_flow_base", referencedColumnName = "id")
private FlowBase flowBase;
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumns({#JoinColumn(name = "process_base_id", referencedColumnName =
"process_base_id"),
#JoinColumn(name = "reference_product_id", referencedColumnName =
"reference_product_id")})
private ProcessTemplate linkedProcessTemplate;
}
BaseEnvironmentalImpact:
#Data
#Entity
#EqualsAndHashCode(onlyExplicitlyIncluded = true)
#Table(name = "base_environmental_impact")
public class BaseEnvironmentalImpact {
#Id
#EqualsAndHashCode.Include
private String id;
private double value;
#ManyToOne
#JoinColumn(name = "fk_methodology", referencedColumnName = "id")
private Methodology methodology;
#ManyToOne
#JoinColumn(name = "fk_impact_category", referencedColumnName = "id")
private ImpactCategory impactCategory;
#ManyToOne
#JoinColumn(name = "fk_impact_indicator", referencedColumnName = "id")
private ImpactIndicator impactIndicator;
#ManyToOne
#JoinColumn(name = "fk_source_info", referencedColumnName = "id")
private SourceInfo sourceInfo;
#Column(name = "version")
#Version
private Long version;
//ref
#ManyToOne
#JoinColumn(name = "fk_elementary_flow_base")
private ElementaryFlowBase elementaryFlowBase;
#ManyToOne
#JoinColumns({
#JoinColumn(
name = "process_base_id",
referencedColumnName = "process_base_id"),
#JoinColumn(
name = "reference_product_id",
referencedColumnName = "reference_product_id")
})
private ProcessTemplate processTemplate;
}
As I wrote I cannot understand why I had an errors log, probably I make a mistake in the relation or cascade but I'm not able to figure out the issue. If I import data they seem correctly inserted so I cannot understand the problem.
Thanks in advance for the help.
SOLVED, EDIT:
I solve only the error on ProcessTemplate-BaseEnvironmentalImpact adding a mappedBy.
I don't include a schema because I think it's autogenerated, I include these parameters in application properties:
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation = true
spring.jpa.hibernate.ddl-auto = create-drop
logging.level.org.hibernate = ERROR
spring.jpa.generate-ddl = true
I also solved other issues adding:
#JoinColumns({
#JoinColumn(name = "fk_pt_process_base_id", referencedColumnName = "process_base_id"),
#JoinColumn(name = "fk_pt_reference_product_id", referencedColumnName = "reference_product_id")
} )

Mapping a composite foreign key to a composite primary key

I'm having problems mapping composite keys in jpa / hibernate. The parent entity and the child entity both have composite primary keys.
I have been able to use #mapsId when the parent entity has a simple key and the child has a composite key.
In the hibernate documentation they use #JoinCoumns in the mapping to demonstrate mapping two composite keys. But in their example its not clear where those column references are defined.
I have the following:
#Embeddable
public class PriceRequestLegKey implements Serializable {
#Column(name = "leg_request_id")
private String requestId;
#Column(name = "display_index")
private int displayIndex;
...
}
#Embeddable
public class AllocationKey implements Serializable {
#Column(name = "leg_request_id")
private String requestId;
#Column(name = "display_index")
private int displayIndex;
#Column(name = "allocation_index")
private int allocationIndex;
...
}
#Entity(name = "PriceRequestLeg")
public class PriceRequestLegModel {
#EmbeddedId
private PriceRequestLegKey legKey;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "leg_request_id", referencedColumnName = "leg_request_id"),
#JoinColumn(name = "display_index", referencedColumnName = "display_index")
})
private List<AllocationModel> allocations;
...
}
#Entity(name = "Allocation")
public class AllocationModel {
#EmbeddedId
private AllocationKey allocationKey;
#ManyToOne
#MapsId
#JoinColumns({
#JoinColumn(name = "leg_request_id", referencedColumnName = "leg_request_id"),
#JoinColumn(name = "display_index", referencedColumnName = "display_index")
})
private PriceRequestLegModel leg;
...
}
At runtime when saving it gives the follow exception:
org.springframework.orm.jpa.JpaSystemException: could not get a field value by reflection getter of com.lbg.legato.rfq.data.entity.AllocationKey.displayIndex; nested exception is org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.lbg.legato.rfq.data.entity.AllocationKey.displayIndex
Which I assume is spurious as there are getters and setters. I also get the same error if I use mappedBy="leg" on the priceRequestLegModel and #MapsId on the AllocationModel. Could anyone point out what I'm doing wrong here?
You should restore the mappedBy="leg" to the PriceRequestLegModel #OneToMany annotation:
#Entity(name = "PriceRequestLeg")
public class PriceRequestLegModel {
#EmbeddedId
private PriceRequestLegKey legKey;
#OneToMany(mappedBy="leg", cascade = CascadeType.ALL)
private List<AllocationModel> allocations;
...
}
Then you should change AllocationKey to reference PriceRequestLegKey:
#Embeddable
public class AllocationKey implements Serializable {
PriceRequestLegKey legKey; // corresponds to PK type of PriceRequestLegModel
#Column(name = "allocation_index")
private int allocationIndex;
...
}
And then set the value of the Allocation.leg #MapsId annotation appropriately:
#Entity(name = "Allocation")
public class AllocationModel {
#EmbeddedId
private AllocationKey allocationKey;
#ManyToOne
#MapsId("legKey")
#JoinColumns({
#JoinColumn(name = "leg_request_id", referencedColumnName = "leg_request_id"),
#JoinColumn(name = "display_index", referencedColumnName = "display_index")
})
private PriceRequestLegModel leg;
...
}
Some examples like this are in the JPA 2.2 spec section 2.4.1.

org.hibernate.AnnotationException: mappedBy reference an unknown target entity property

I am trying to make a OneToMany relationship between User and Project but I am getting following error:
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: ProjectDTO.FKUser in UserDTO.projectDTOs
My User class look like below
#Entity
#Table(name = "USER")
public class UserDTO implements java.io.Serializable {
private Integer iduser;
private Set<ProjectDTO> projects = new HashSet<ProjectDTO>(0);;
public UserDTO() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "IDUser", unique = true, nullable = false)
public Integer getIduser() {
return this.iduser;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "FKUser")
public Set<ProjectDTO> getProjectDTOs() {
return projects;
}
}
And my Project class looks like
#Entity
#Table(name = "Project")
public class ProjectDTO implements java.io.Serializable {
private Integer idproject;
private UserDTO FKUser;
public ProjectDTO() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "IDProject", unique = true, nullable = false)
public Integer getIdproject() {
return this.idproject;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "FKUser", referencedColumnName = "IDUser")
public UserDTO getUserDTO() {
return FKUser;
}
}
I went through some similar questions but I was unable to figure out where I was going wrong. Maybe I am missing something very obvious.
Thanks a lot
In mappedBy you must use field name (or part of the getter name without get for property-based access), not column name.
//...
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userDTO")
public Set<ProjectDTO> getProjectDTOs() {
return projects;
}
//...
Note: also need to add setters.
mappedBy needs to point to the entity that does the mapping, so I believe it should be mappedBy="USER"

Many to Many in JPA and EBean

I'm trying to make a many to many relationship using EBean in Play2 and I have an issue where EBean trows an error saying my class is not registered.
Heres my mapping classes:
#Entity
public class Booking extends Model {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//... other fields
}
#Entity
public class Store extends Model {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//... other fields
}
#Embeddable
public class ComissionId {
#ManyToOne(targetEntity = Booking.class, optional = false)
#PrimaryKeyJoinColumn(name = "booking_id", referencedColumnName = "id")
private Booking booking;
#ManyToOne(targetEntity = Store.class, optional = false)
#PrimaryKeyJoinColumn(name = "store_id", referencedColumnName = "id")
private Store store;
}
#Entity
#AssociationOverrides({
#AssociationOverride(name = "id.booking", joinColumns = #JoinColumn(name = "booking_id")),
#AssociationOverride(name = "id.store", joinColumns = #JoinColumn(name = "store_id"))
})
public class StoreComission extends Model {
#EmbeddedId
private ComissionId id;
#Column(nullable = false)
private double value;
#Column(nullable = false)
private Date date;
}
The error:
java.lang.RuntimeException:
Error reading annotations for models.ids.ComissionId
Caused by: java.lang.RuntimeException:
Error with association to [class models.Booking] from [models.ids.ComissionId.booking].
Is class models.Booking registered?
In my application.conf I've put ebean.default="models.*" so all this classes should be registered right? (I've tried to move the ComissionId from the package models.ids to models, but the same error ocurred)
You have this error because of #ManyToOne annotations inside your ComissionId class. To make this code work you have to move these relations to StoreComission class. In ComissionId class you should leave only identifiers. In StoreComission class #ManyToOne relation are mapped to the same columns as fields from composite key. But they have attributes 'insertable' and 'updateable' set to false to prevent column duplication.
Here is corrected working code for above scenario:
StoreComission class:
#Entity
public class StoreComission extends Model {
public StoreComission() {
id = new ComissionId();
}
#EmbeddedId
private ComissionId id;
#Column(nullable = false)
public double value;
#Column(nullable = false)
public Date date;
#ManyToOne
#JoinColumn(name = "booking_id", insertable = false, updatable = false)
private Booking booking;
#ManyToOne
#JoinColumn(name = "store_id", insertable = false, updatable = false)
private Store store;
public void setBooking(Booking aBooking) {
booking = aBooking;
id.booking_id = aBooking.id;
}
public Booking getBooking() {
return booking;
}
public void setStore(Store aStore) {
store = aStore;
id.store_id = aStore.id;
}
public Store getStore() {
return store;
}
}
ComissionId class:
#Embeddable
public class ComissionId {
public int booking_id;
public int store_id;
#Override
public int hashCode() {
return booking_id + store_id;
}
#Override
public boolean equals(final Object obj) {
return super.equals(obj);
}
}

Categories

Resources