EclipseLink composite PK with FK - java

I am using eclipselink 2.5.1.
Let's say I have these two class.
JAVA
#Entity
public class Car implements Serializable {
#EmbeddedId
protected CarPK carPK;
private String color;
#ManyToOne(fetch = FetchType.LAZY)
private Manufacturor manufacturor;
//constructors, getters & setters...
}
#Embeddable
public class CarPK implements Serializable {
#NotNull
private int idManufacturor;
#Temporal(javax.persistence.TemporalType.DATE)
private Date date;
//constructors, getters & setters...
}
Car has a composite primary key (idManufacturor and date) and idManufacturor is also a foreign key referencing the class Manufacturor.
I'm having issue with the mapping. EclipseLink understand the manufacturor object as a column in my Car table.
Error
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: invalid column name : 'manufacturor'.
I know the problem will be solved if I add a column manufacturor FK but it would be repeating.
Please feel free to ask for any precision if I'm not clear enough.
Thank you for your help.

Add the JoinColumn Annotation
#JoinColumn(name = "id_manufacturor", referencedColumnName = "id")
Name is the FK column name in your database (not entity).
The referencedColumnName "id" must correspond to the defined id in manufacturer table.

Related

How to create table with unidirectional relation in Hibernate?

i have the empty database in mysql, and two java entites. One of those have unidirectional relation. When hibernate tryes to create tables, i got the error:
Error executing DDL "alter table entry add constraint FK6ov2k83sx3crs9v3q8nvjuf1j foreign key (category_name) references category (name)" via JDBC Statement
There are my entites:
#Entity
public class Entry {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY)
private int id;
#Column
private String myfio;
private String descr;
#OneToOne(cascade = CascadeType.ALL)
private Category category;
}
And the second:
#Entity
#Table(name="category")
public class Category {
#Id
#Column
private String name;
}
How to create tables without errors?
OneToOne relationship shares the same id. So it should be the same type, but the first one is int (actually it should be Integer to allow null value for the transient (not stored) entities) and the second one is String. It seems you simply missed a line. Also, it worths to mention Vlad Mihalchea’s article https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

Hibernate-OneToMany mapping for existing DB Tables

I am trying to join to Hibernate Entities in a OneToOne Mapping. I am able to fetch the data for a given primary key from the Main Entity, the joining entity, however, returns null. I am new to hibernate and any help will be appreciated.
I have two Tables,
PT_CORE
Primary Key: ptId - Integer;
Foreign Key: stId(ST_AUX) - Integer;
Columns: ptId, ptName
ST_AUX
Primary Key: stId;
Columns: stId, stName
The two tables get populated by other applications and mine is a read-only operation.
Below is my first Entity class(PtCore.java)
#Entity
#Table(name="PT_CORE")
public class PtCore implements Serializable{
#Id
#Column(name="ptId", nullable = false)
private int id;
#Column(nullable=false)
private int stId; //The Foreign key column
#OneToOne
#JoinTable( name = "core_aux", joinColumns = {#JoinColumn(Name="ptId")},
inverseJoinColumns = {#JoinColumn(Name="stId")}
)
private StAux staux;
//Getters, setters and toString() for above
}
StAux is another Entity, defined as below,
#Entity
#Table(name="ST_AUX")
public class StAux implements Serializable {
#Id
#Column(nullable=false)
private Integer stId;
#OneToOne
private PtCore ptcore;
#Column
private String stName;
//Getters, Setters and toString follow.
}
I do below in the Service method:
PtCore obj = (PtCore) session.get(PtCore.class,1);
System.out.println(obj);
In the Results, I get the value of ptName, but the stAux class variables are null, Indicating that the join does not work as expected.
First of all you have the mapping information existing in your PT_CORE. And I assume it is something like FOREIGN KEY (stid) REFERENCES (stid). If you want to use existing schema and existing data I guess there is no mapping table core_aux really existing. At least you did not mention it. However it is visible as #JoinTable annotation but still there is this above mentioned foreign key which seems to be the real mapping (so again not the join table).
I suggest the following
remove this
#Column(nullable=false)
private int stId; //The Foreign key column
from your PtCore. I think it is not needed. Also in PtCore, remove the #JoinTable (because what I told above) and add mapping informaiion to #OneToOne annotation, like:
#OneToOne
#JoinColumn(name = "stid")
private StAux staux;
from your PT_CORE.
Then in StAux alter also a bit:
#Id
#Column(name = "stid") // this might not be needed but if there is like "st_id"...
private Integer stId; // so just for sure
#OneToOne(mappedBy = "staux")
private PtCore ptcore;
Because you have existing tables and constraints there might raise errors if hibernate tries to auto-generate those again by JPA instructions.
Check this for example for more information.
UPDATE: just realized also that in your title is #OneToMany but in your code is #OneToOne.
So you might want to elaborate your question and/or title a bit.
In your relation, the owning side is PtCore, the inverse side is StAux.
In bidirectional OneToOne relations, the inverse side has to have the mappedBy attribute. Actually, the mappedBy attribute contains the name of the association-field on the owning side.
So, you must change your inverse side code (StAux Entity). You have to add mappedBy attribute to #OneToOne in StAux class:
#OneToOne(mappedBy="staux")
private PtCore ptcore;

Hibernate: Using part of composite FK in another entity PK

im relative new to Hibernate Mappings im trying to achieve this functionality between the class Post and Comentario without luck
Relational model
#Embeddable
public class PostPK implements Serializable {
#Column(name="idPost")
private int postID;
#Column(name="idUsuario")
private int userIDFK;
-------------------------------
#Entity
#Table(name="Post")
public class Post {
#EmbeddedId
private PostPK id;
#ManyToOne
#MapsId(value="userIDFK")
#JoinColumn(name="idUsuario")
private Usuario usuario;
#OneToMany(mappedBy="post")
private List<Comentario> comentarios;
#Column(name="titulo")
private String titulo;
-----------------------------------
#Embeddable
public class ComentarioPK implements Serializable{
#Column(name="idComentario")
private int comentarioId;
#Column(name="idPost")
private int postIdFK;
---------------------------
#Entity
#Table(name="Comentario")
public class Comentario {
#EmbeddedId
private ComentarioPK id;
#ManyToOne
#MapsId("postIdFK")
#JoinColumn(name="idPost",referencedColumnName="idPost")
private Post post;
#Column(name="texto")
private String texto;
without mapping comentario and its fields in Post its working fine but when i decide to map it i get this error
Unable to find column reference in the #MapsId mapping: idUsuario
is it not finding the idUsuario column in Comentario table? i dont want to add it , i can achieve joins in mysql but i dont know how to do it in Hibernate
#MapsId annotation is used to map the primary key fields of the parent entity with the child entity(with the same name).
In your case your are having composite primary key in your parent entity but in child entity you want to refer only one field of it.
PostPK has two fields : idPost and idUsuario. But in Comentario class when your are specifying ManyToOne relationship you are mentioning single column in #JoinColumn(which is idPost) and no field for idUsuario is available in your mapping. But as per the behavior of #MapsId annotation both the fields(idPost and idUsuario) are expected in Comentario class.
Thus, in your case #MapsId annotation won't work

How to map weak entity hibernate

I have the following relation in database:
I have one strong table.
I have one weak table that has one to one relation with strong table. Really it's 0 to 1 relation, because strong table doesn't have always one line in weak table. To identify this weak table is enough the Id of strong table.
And finally I have another weak table, with ManyToOne relation with first weak entity. It needs the id of OneToOneWeakEntity (that also is id of strong table), and his own id. It's like an historical of OneToOneWeakTable.
I want to map in Hibernate, but I don't know how to do it.
Now I have the following code:
#Entity
#Table(name="table")
public class Table {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id_table")
private Integer idTable;
private String otherAtributes;
....
}
#Entity
#Table(name="oneToOneWeakTable")
public class OneToOneWeakEntity {
#OneToOne(cascade = CascadeType.ALL, optional=false)
#Id
#JoinColumn(name="table_id_table")
private Table table;
private String otherAtributes;
....
}
#Entity
#Table(name="oneToManyWeakTable")
#IdClass(EntityPk.class)
public class OneToManyWeakTable {
#Id
#ManyToOne
#JoinColumn(name="table_id_table")
private OneToOneWeakEntity oneToOneWeakEntity;
#Id
#Column(name="own_id")
private String ownId;
private String otherAtributes;
....
}
class EntityPk {
#Id
#ManyToOne
#JoinColumn(name="table_id_table")
private OneToOneWeakEntity oneToOneWeakEntity;
#Id
#Column(name="own_id")
private String ownId;
private String otherAtributes;
....
}
My problem is when I try to run my application, because I have this deployment error:
Caused by: org.hibernate.AnnotationException: A Foreign key refering package.OneToOneWeakEntity from package.OneToManyWeakTable has the wrong number of column. should be 0
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:502)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:117)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1518)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1422)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
How can I map this relation??
Thanks!
Edit: I also try with this to map OneToOneWeakTable:
#OneToOne(cascade = CascadeType.ALL, optional=false)
#PrimaryKeyJoinColumn
#Id
#JoinColumn(name="table_id_table")
private Table table;
In this case, I also have an error when I try to deploy, but a different exception:
Caused by: java.lang.NullPointerException
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:568)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1518)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1422)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
You don't have to repeat the annotations in the EntityPK class, you just need to match simple primitive attribute that represent the compound key of OneToManyWeakTable, you should get something like this (note insertable and updatable attributes, it has no sense modify the association because it is part of entity instance's pk),
#Entity
#Table(name="oneToManyWeakTable")
#IdClass(EntityPk.class)
public class OneToManyWeakTable {
#Id
#Column(name="table_id_table")
private long weakEntity
#ManyToOne
#JoinColumn(name="table_id_table", insertable=false, updatable=false)
private OneToOneWeakEntity oneToOneWeakEntity;
#Id
#Column(name="own_id")
private String ownId;
private String otherAtributes;
....
}
class EntityPk {
private long weakEntity;
private String ownId;
....
}
#Entity
#Table(name="oneToOneWeakTable")
public class OneToOneWeakEntity {
#OneToOne
#Id
#JoinColumn(name="table_id_table")
private Table table;
private String otherAtributes;
....
}
Also take a look at some official doc of compound primary keys
Edit: add the OneToOneWeakTable assuming that you are using JPA 2, in your edit you are mixing annotation. Check the id fileds and attribute that share the entities, must be same type (note that I use long for weakEntity attribute just as an example).

Hibernate disable default behaviour

I have a problem with my Hibernate making assumptions on what to call columns.
Specifically, when I do a #ManyToOne field, where I refer to a column in the other Table.
What happens is that, If I do not enter a #JoinColumn annotation as well, it maps the field with an underscore in it's name.
For example, i have this class:
#Entity
public class User extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userFK")
private List<TwitterAccount> twitterAccounts;
/* GETTERS & SETTERS OMITTED */
}
And then I have the TwitterAccount class:
#Entity
public class TwitterAccount extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
private User userFK;
}
What happens is that when it tries to get the Twitter accounts for a certain user, I get the exception: MySQLSyntaxErrorException: Unknown column 'twitteracc1_.userFK_id' in 'field list'
Look at what it tries to map the userFK to: userFK_id. Of course it doesn't exist! I haven't given it that name.
So the question comes down to: Is it possible to turn off this functionality? (The functionality that turns the column name into 'field_'foreignkey')
I am aware that using #JoinColumn(name = "userFK") would solve it, but I'd rather turn it off instead.
Regards
This is the default as specified by the JPA specification
The concatenation
of the following: the name
of the referencing relationship
property or field of the referencing
entity or embeddable class;
""; the name of the referenced
primary key column. If there is no
such referencing relationship
property or field in the entity, or if
the join is for an element collection,
the join column name is
formed as the concatenation of the
following: the name of the entity;
""; the name of the referenced
primary key column.
In hibernate this is implemented in a NamingStrategy in this case the EJB3NamingStrategy. You can implement your own version of this deciding whatever you want to use. But that will probably only complicate/confuse people (which might expect the standards to apply).

Categories