JPA HIBERNATE - mapping a column twice (embeddedID and POJO) - java

I have to map a badly designed DB. And in the class "cote" there a composed PK with FK fields. So i made an embeddedable to avoid using derived entities with IdClass. So I tried this :
#Entity
#Table(name="EVA_COTE")
public class Cote implements Serializable{
/**
*
*/
private static final long serialVersionUID = -3902534586060936635L;
#EmbeddedId
private CotePK cotePK;
#ManyToOne
#JoinColumn(name="Evaluation", referencedColumnName = "NUDOSS")
private Evaluation evaluation;
#ManyToOne
#JoinColumn(name="CRITERE", referencedColumnName = "CODE")
private Critere critere;
#ManyToOne
#JoinColumn(name="SEUIL", referencedColumnName = "CODE")
private Seuil seuil;
#Column(name="VALEUR", columnDefinition="Decimal(5,0)")
private Integer valeur;
#Column(name="OBSERVATIONS", length=500)
private String observations;
With the following EmbeddedId :
#Embeddable
public class CotePK implements Serializable{
/**
*
*/
private static final long serialVersionUID = 6835265195560184935L;
#Column(name="Evaluation", nullable=false)
private Integer evaluationId;
#Column(name="CRITERE", nullable =false)
private String critereId;
#Column(name="SEUIL", nullable=false)
private String seuilId;
As you can see i use the columns evaluation critere and seuil once in the embeddedId and once in the class Cote. And of course it doesn't work and i don't know what to try anymore. Is there a way to force JPA to link the two fields?

My final solution :
#Entity
#Table(name="EVA_COTE")
public class Cote implements Serializable{
/**
*
*/
private static final long serialVersionUID = -3902534586060936635L;
#EmbeddedId
private CotePK cotePK;
#ManyToOne
#MapsId("evaluationId")
#JoinColumn(name="EVALUATION", referencedColumnName = "NUDOSS")
private Evaluation evaluation;
#ManyToOne
#MapsId("critereId")
#JoinColumn(name="CRITERE", referencedColumnName = "CODE")
private Critere critere;
#ManyToOne
#MapsId("seuilId")
#JoinColumn(name="SEUIL", referencedColumnName = "CODE")
private Seuil seuil;

Add this annotation to composite primary key
#EmbeddedId
#AttributeOverrides( {
#AttributeOverride(name="column_varible_name_1", column=#Column(name="column_name_1", nullable=false, length=<x>) ),
#AttributeOverride(name="column_varible_name_2", column=#Column(name="column_name_2", nullable=false, length=<x>) ) } )

Related

Making primary key same as foreign key in Hibernate entity

I am new to Hibernate. I am working on two entities as follows:
Entity 1 is as follows:
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#OneToOne
#JoinColumn(unique = true)
private User user; <--- HOW WILL I DENOTE THIS PRIMARY KEY OF VMUSER ENTITY ?
In the associated table in mysql i.e. vm_user, user_id is both primary key as well as foreign key which refers to id of user table associated with User entity.
Entity 2 is as follows:
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#ManyToOne
private A a;
#OneToOne
#JoinColumn(unique = true)
private B b;
In the associated table in mysql i.e. my_entity, primary key is a combination of id of a and id of b. I am not getting how to denote this in Hibernate entity MyEntity.
Regarding the same, I have gone through a few posts: Hibernate foreign key as part of primary key and JPA & Hibernate - Composite primary key with foreign key, but no getting idea how to do these two ?
The solution is #MapsId
For example
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
#Id
#Column(name = "user_id")
private Integer id;
#MapsId
#OneToOne
private User user;
You can also remove the #JoinColumn(unique = true) because #Id makes it unique already.
public class MyEntityPk implements Serializable {
private Integer aId;
private Integer bId;
// IMPORTANT: Override equals() and hashCode()
}
#IdClass(MyEntityPk.class)
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
#Id
private Integer aId;
#Id
private Integer bId;
#MapsId("aId")
#ManyToOne
private A a;
#MapsId("bId")
#OneToOne
private B b;
Please find more information in the Hibernate documentation https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#identifiers-derived
You need to use #EmbeddedId and #MapsId ,
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
#Id
#Column(name = "user_id")
private Integer id;
#MapsId("user_id")
#OneToOne
private User user;
}
You can do the same thing for MyEntity as below,
#Embeddable
class BKey {
private int aId;
private int bId;
}
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
#EmbeddedId
private BKey primaryKey;
#MapsId("aId")
#ManyToOne
private A a;
#MapsId("bId")
#OneToOne
#JoinColumn(unique = true)
private B b;
}
VM Users class
public class VmUser implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#OneToOne
#JoinColumn(name="ID")
private Users user;
Users class
public class Users implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#OneToOne(mappedBy="user")
private VmUser vmUser;
A class
#Entity
public class A implements Serializable {
#Id
private long id;
#OneToMany(mappedBy="a")
private List<MyEntity> myEntitys;
B Class
#Entity
public class B implements Serializable {
#Id
private long id;
#OneToMany(mappedBy="b")
private List<MyEntity> myEntitys;
MyEntity class
#Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private MyEntityPK id;
#ManyToOne
#JoinColumn(name="ID1")
private A a;
#ManyToOne
#JoinColumn(name="ID2")
private B b;
MyEntityPK class
#Embeddable
public class MyEntityPK implements Serializable {
#Column(insertable=false, updatable=false)
private long id1;
#Column(insertable=false, updatable=false)
private long id2;

Sping Data return List of null elements, but List has much elements

i have a problem
I have two entities:
Entity ALBERO
#Entity
#IdClass(Albero.class)
#Table(schema="organo", name = "albero")
public class Albero implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#JoinColumn(name = "cmu")
#OneToOne
private Struttura cmu;
#Id
#JoinColumn(name = "padre")
#NotFound(action = NotFoundAction.IGNORE)
#ManyToOne
private Struttura padre;
#Column(name = "div")
private Date div;
#Column(name = "dfv")
private Date dfv;
#Column(name = "cso", length=15)
private String cso;
... get and set methods
and Entity STRUTTURA
#Entity
#Table(schema="organo", name="strutture")
#SqlResultSetMapping(
name = "Albero",
classes = #ConstructorResult(
targetClass = Albero.class,
columns = {
#ColumnResult(name="cmu", type=String.class),
#ColumnResult(name="padre", type=String.class)
}
)
)
public class Struttura implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "cmu")
private String cmu;
#Column(name = "nome", length=512)
private String nome;
#Column(name = "tipologia")
private String tipologia;
#Column(name = "data_creazione")
private Date data_creazione;
...get and set methods
I have a Repository AlberoRepository with the method:
public List<Albero> findByDfvIsNull();
and other method with native query:
String QUERY = "SELECT a.* FROM ALBERO a WHERE DFV IS NULL";
#Query(nativeQuery = true, value = QUERY)
public List<Albero> findAllWithDfvIsNull();
La query on Oracle DB, give me a result with 802 record.
Each record are full; they have the values.
Instead, the methods Java, give me a List of 802 object
BUT THESE OBJECTS ARE NULL.
Why ?
Can you help me ?
Thank you very much
The problem in #IdClass annotation.
You need a special class for PK:
public class AlberPK implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#JoinColumn(name = "cmu")
#OneToOne
private Struttura cmu;
#Id
#JoinColumn(name = "padre", nullable = true)
#NotFound(action = NotFoundAction.IGNORE)
#ManyToOne
private Struttura padre;
}
... and change a little in Albero.class:
#Entity
#IdClass(AlberPK.class)
#Table(schema = "organo", name = "albero")
public class Albero implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Struttura cmu;
#Id
private Struttura padre;
...
}
That have to work.
I am really don't understand - why you used complex PK? Re-mind your DB structure if possible. It will help you a lot in future.

How to make a foreign key in EmbeddedId to other Entity with other EmbeddedId

I have the class SWEntity that is central to the problem. I want set of classes SWEntityRow that is a detail of the SWEntity (one entity has many rows). The SWentity has in the key two other classes in the embeddedId Area and Procedure. When I try to map SWEntity with SWEntityRow using SWEntityRowId I take differents errors.
Some idea how I can map SWEntityRowId with SWEntity?
This is a simplified picture of the ER: https://i.stack.imgur.com/pMJzh.png
And this are my simplified classes:
SWentity
-----------
#Entity
public class SWEntity {
#EmbeddedId
private SWEntityId id;
[...]
}
SWEntityId
-------------
#Embeddable
public class SWEntityId implements Serializable{
private static final long serialVersionUID = 1L;
#NotNull
private String name;
#NotNull
private int version;
#ManyToOne
#JoinColumn(name = "areaName", nullable = false)
#JsonIgnore
private Area area;
#ManyToOne
#JoinColumn(name = "procedureName", nullable = false)
#JsonIgnore
private Procedure procedure;
}
SWEntityRow
---------------
#Entity
public class SWEntityRow{
#EmbeddedId
private SWEntityRowId sWEntityRowId;
}
SWEntityRowId
---------------
#Embeddable
public class SWEntityRowId implements Serializable {
private static final long serialVersionUID = 1L;
private String rowName;
//SWEntityId
#ManyToOne
#JoinColumns({
#JoinColumn(name="name_row", referencedColumnName="name"),
#JoinColumn(name="version_row", referencedColumnName="version"),
#JoinColumn(name="area_row", referencedColumnName="area_name"),
#JoinColumn(name="procedure_row", referencedColumnName="procedure_name"
})
}
This resolve my question
# JoinColumns({
#JoinColumn(name="entityname", referencedColumnName="name"),
#JoinColumn(name="entityversion", referencedColumnName="version"),
#JoinColumn(name="entityarea", referencedColumnName="AreaName"),
#JoinColumn(name="entityprocedure", referencedColumnName="ProcedureName")
})
The difference is in referencedColumnName="AreaName" not referencedColumnName="area_name" and the same for procedure.
Thanks!
Just one change required
#Entity
public class SWEntity {
#Id
#EmbeddedId
private SWEntityId id;
[...]
}

How create a constraint with Hibernate?

How can I create a constraint with Hibernate? I'm mapping two classes, "Team" and "Match", but I want that a match JUST can happens if the teams are from the same League. The way that I'm doing right now I can create a match with teams from differents leagues (which isn't interesting in this case).
Is there some annotation that "wraps" my teams, home and away, just being from one league? Or I have to do this in my system?
Thanks.
#Table(name = "match")
#Entity
public class Match implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#ManyToOne
#JoinColumn(name = "id_league")
private League league;
#ManyToOne
#JoinColumn(name = "id_home", referencedColumnName="id")
private Team home;
#ManyToOne
#JoinColumn(name = "id_away", referencedColumnName="id")
private Team away;
#Column
private Integer goalsHome;
#Column
private Integer goalsAway;
#Temporal(value = TemporalType.DATE)
private Date matchDate;
and
#Table(name="team")
#Entity
public class Team implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(length = 55)
private String name;
#ManyToOne
#JoinColumn(name = "id_league")
private League league;
#OneToMany
private List<Match> match;

JPA OneToMany, ManyToOne bidirectional

I'm trying to get rid of the following error:
The attribute [lcritical] in entity
class [class
pl.pwc.docs.pl704.PL704_Error] has a
mappedBy value of [pl704_error] which
does not exist in its owning entity
class [class
pl.pwc.docs.pl704.PL704_Error_Critical].
If the owning entity class is a
#MappedSuperclass, this is invalid,
and your attribute should reference
the correct subclass.
PL704 #Entity class:
#Entity
public class PL704 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private int Status;
private String Comments;
#OneToMany(mappedBy="pl704", cascade=CascadeType.ALL, targetEntity=PL704_Error.class, fetch=FetchType.EAGER)
private Collection lerror = new ArrayList<PL704_Error>();
//getters, setters...
PL704_Error #Entity class:
#Entity
public class PL704_Error implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String ErrorType;
private String ErrorReason;
private String ErrorLocation;
private String OriginalAttributeValue;
#ManyToOne
#JoinColumn(name = "PL704_ID", referencedColumnName = "ID")
private PL704 pl704;
#OneToMany(mappedBy="pl704_error", cascade=CascadeType.ALL, targetEntity=PL704_Error_Critical.class, fetch=FetchType.EAGER)
private Collection lcritical = new ArrayList<PL704_Error_Critical>();
//getters, setters...
PL704_Error_Critical #Entity class:
#Entity
public class PL704_Error_Critical implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "PL704_ERROR_ID", referencedColumnName = "ID")
private PL704_Error error;
//getters, setters...
Summing up, One PL704 can have many PL704_Error. One PL704_Error can have many PL704_Error_Critical.
How should I change my code to fix an error?
Used: EclipseLink 2.1.1, H2 Embedded.
It should be
#OneToMany(mappedBy="error", cascade=CascadeType.ALL,
targetEntity=PL704_Error_Critical.class, fetch=FetchType.EAGER)
private Collection lcritical = new ArrayList<PL704_Error_Critical>();
look at the corresponding property name in PL704_Error_Critical:
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "PL704_ERROR_ID", referencedColumnName = "ID")
private PL704_Error error;
The mapped by attribute spelling is not correct, maybe this is the cause:
In class PL704_Error the lcritical attribute is reversed mappedBy Attribute
#OneToMany(mappedBy="pl704_error"...
But the variable in PL704_Error_Critical is called only error.

Categories

Resources