Spring JPA table relationship naming convention - jpa

I have to entities:
#Entity
#Table(name = "users")
public class User {
...
#OneToMany
private Set<AvatarExecution> user_executions;
...
}
And the second one
#Entity
#Table(name = "user_executions")
public class UserExecution {
...
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private User user;
...
}
Database is postgres, and contains two tables:
users
user_executions
When I try to execute query, like: findAll on two tables I get the following error:
jdbc.spi.SqlExceptionHelper : ERROR: relation "users_user_executions" does not exist
How Spring/Hibernate naming strategy works? What should I do?
I just want that Spring Boot app will look up for
user_executions

Seem like there is a typo error, in #OneToMany you used the entity AvatarExecution, and in #ManyToOne is included in entity UserExecution.
Usually, in Java, we use the camelCase naming convention. I suggest changing the user_executions to userExecutions or executions (of the property/field in the class UserExecution, not table name) and using the mappedBy property in #OneToMany annotation.
You can check for this article about using #OneToMany and #ManyToOne with mappedBy.

Related

How to use multiple foreign keys in JPA?

I'm starting a project to know more in detail JPA.
Context:
At the end of his internship, the student has a report to make and a presentation in front of his professor to do about the internship.
I've a database, which is called "grade_management". It must contains a "student", "presentation", "report", "professor" and a "mark" (there are several rating criteria such as expression, quality of powerpoint ...) table. But now it's empty, since I want to make it throught JPA.
I've a "Presentation" class. Which countain this:
#Entity
public class Presentation implements Serializable {
#Id
#GeneratedValue (strategy=GenerationType.AUTO)
private int presentation_id;
private Date date;
private mark_id;
private int professor_id;
public Soutenance() {}
public Soutenance(Date date) {
this.date = date;
}
}
But the Presentation table contain 2 foreign key: professor_id and mark_id.
My question is: How can I indicate that both of them are foreign key ?
I'm sorry if I'm not clear, don't hesitation to ask question.
Cordially
You shouldn't reference other entities by their ID, but by a direct reference to the entity.
Something like that :
#ManyToOne
#JoinColumn(name = "mark_id", referencedColumnName = "id")
private Mark mark; // supposed here that mark_id if link to entity `Mark`
#ManyToOne
#JoinColumn(name = "professor_id", referencedColumnName = "id") // suppose "id" is the column name of the PK inside the table Professor.
private Professor professor; // supposed here that professor_id if link to entity `Professor`
This code is supposing that you use an unidirectional relation.
For bidirectional you have to define this in the other side (Mark/Professor type)
#OneToMany(mappedBy = "professor")
private Presentation presentation;
From your explanation, it looks like you have a Database named grade_management and in that database you have "student", "presentation", "report", "professor" and a "mark" tables (i.e: which are #Entity by themselves defined in their separate respective classes )
I'm not sure whether you have defined them or not. If not then you have to define them first and then use the refactored code mentioned below.
So, you will have many-to-one relation mapping. You can annotate your foreign keys belonging to different tables using #ManyToOne annotation to indicate relation type and #JoinColumn annotation to indicate that this entity has a foreign key to the referenced table.
You can redefine your Presentation class show below:
#Entity
#Table(name = "Presentation")
public class Presentation implements Serializable {
#Id
#Column(name="presentation_id")
#GeneratedValue (strategy=GenerationType.AUTO)
private int presentation_id;
private Date date;
#ManyToOne
#JoinColumn(name = "mark_id")
private Mark mark_id;
#ManyToOne
#JoinColumn(name = "professor_id")
private Professor professor_id;
public Soutenance() {}
public Soutenance(Date date) {
this.date = date;
}
//getter and setter
}
Also, if you need more information to read upon for yourself you can always checkout this Hibernate Documentation that explains everything you'll need to know.

OpenJPA cascade persist on OneToOne relationship

I'm trying to persist to an IBM DB2 database using Websphere which in turn uses an OpenJPA implementation. My issue is that i'm always getting an integrity constraing exception SQLCODE=-530, meaning it can't find the foreign key.
The relationship is as follows
#Entity
public class A{
#Id
private String id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "B_ID")
private B b;
}
#Entity
public class B{
#Id
private String id;
}
Now i try to persist the two entities.
final A a = new A();
final B b = new B();
a.setB(b);
em.persist(a);
The DB owner of the relationship is the table bound to A containing a reference to B while B has no reference to A.
Now when persisting OpenJPA tries to persist the owner of the #JoinColumn first which results in class B not being there and thus isn't able to persist.
Does anybody have a sollution to this issue maitaining the current relationships.
I've already found this post: http://openjpa.208410.n2.nabble.com/Constraint-violation-using-OneToOne-relationship-td6978223.html
but the sollution proposed there doesn't seem to work.

Exception using Compsite Keys on EclipseLink

Im having trouble using composite primary keys with JPA EclipseLink. The problem is when I theres a foreign key that is the primary key of another table. I have this simple scenario.
User
public class Users implements Serializable {
...
private Collection<UserCompany> userCompanyCollection;
#JoinColumn(name = "user_roles", referencedColumnName = "user_role_id")
#ManyToOne(optional = false)
private UserRoles userRoles;
...
}
User Roles
public class UserRoles implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected UserRolesPK userRolesPK;
…
}
User Roles PK
#Embeddable
public class UserRolesPK implements Serializable {
#Basic(optional = false)
#Column(name = "user_role_id")
private int userRoleId;
#Basic(optional = false)
#NotNull
#Column(name = "user_role_company_id")
private int userRoleCompanyId;
...
}
With that objects, I get this exception:
Caused by: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field userRoles] from the entity class [class jpa.Users] is incomplete. When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns. Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.exceptions.ValidationException.incompleteJoinColumnsSpecified(ValidationException.java:1805)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor.getJoinColumnsAndValidate(MappingAccessor.java:575)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.MappingAccessor.getJoinColumns(MappingAccessor.java:525)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOneToOneForeignKeyRelationship(ObjectAccessor.java:629)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ObjectAccessor.processOwningMappingKeys(ObjectAccessor.java:686)
at org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.ManyToOneAccessor.process(ManyToOneAccessor.java:119)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processOwningRelationshipAccessors(MetadataProject.java:1432)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage3(MetadataProject.java:1667)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:521)
at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:526)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1320)
... 36 more
|#]
Thanks in advance for all the help.
Regards,
Daniel
JPA requires using the full primary key in relationship mappings, which is why it doesn't like your mapping - you are not using the user_role_company_id pk field. If user_role_id is enough to uniquely identify userRoles, then it should not be using a composite key and instead only use the single field.
EclipseLink is capable of mapping foreign keys to non or incomplete ID fields, but I recommend against it: Entities are cached on their primary keys, so resolving relationships may require unnecessary database queries even when the entity is in the cache already. Mapping it requires using a customizer to either create or modify the mapping. An example using a customizer is here
http://wiki.eclipse.org/EclipseLink/Examples/JPA/MappingSelectionCriteria

Avaje Ebean. ManyToMany deferred BeanSet

I am writing small app, using Play Framework 2.0 which uses Ebean as ORM.
So I need many-to-many relationship between User class and UserGroup class.
Here is some code:
#Entity
public class User extends Domain {
#Id
public Long id;
public String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public Set<UserGroup> groups = new HashSet();
}
#Entity
public class UserGroup extends Domain {
#Id
public Long id;
public String name;
#ManyToMany(mappedBy="groups")
public Set<User> users = new HashSet();
}
Database scheme generator generates good scheme for that code with intermediate table and all work quite ok, till I using many-to-many.
So I am adding group in one request:
user.groups.add(UserGroup.find.byId(groupId));
user.update();
And trying output them to System.out in another:
System.out.println(user.groups);
And this returns:
BeanSet deferred
Quick search show that BeanSet is lazy-loading container from Ebean. But seems like it doesn't work in proper way or I missed something important.
So is there any ideas about what I am doing wrong?
You need to save associations manually
user.groups.add(UserGroup.find.byId(groupId));
user.saveManyToManyAssociations("groups");
user.update();

Why JPA-2.0 Primary Key Classes have to implement Serializable but my example works without?

In many sources I have read PrimaryKey Classes and even JPA2 entities should be serializable.
IN my example (legacy database) there is a relationship between employee and languages:
Employee Class:
#Entity
#IdClass(EmpleadoId.class)
#Table(name = "NO_INFGRAEMPL")
public class Empleado {
#Id
#Column(name = "IGECOMPANIA", unique = true)
private String compania;
#Id
#Column(name = "IGENUMEROIDENTIFIC", unique = true)
private String numeroIdentificacion;
//...
}
Employee Compound PrimaryKey Class:
public class EmpleadoId {
private String compania;
private String numeroIdentificacion;
//...
}
Employee Language SKill Class:
#Entity
#IdClass(IdiomaEmpleadoId.class)
#Table(name = "NO_IDIOMEMPLE")
public class IdiomaEmpleado {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns(value = {
#JoinColumn(name= "IEMCOMPANIA", referencedColumnName = "IGECOMPANIA"),
#JoinColumn(name = "IEMEMPLEADO", referencedColumnName = "IGENUMEROIDENTIFIC")
})
private Empleado empleado;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "IEMIDIOMA")
private Idioma idioma;
#Column(name = "IEMNIVELLECTURA")
private String nivelLectura;
//...
}
Employee Language Skill Compound PrimaryKey Class:
public class IdiomaEmpleadoId {
private EmpleadoId empleado;
private String idioma;
//...
}
Language Class:
#Entity
#Table(name = "NO_IDIOMAS")
public class Idioma {
#Id
#Column(name = "IDICODIGO")
private String codigo;
#Column(name = "IDIDESCRIPCION")
private String descripcion;
//...
}
I am using EclipseLink JPA2 Provider under a J2SE application and it is not giving me any exceptions.
My questions are:
Why is it not giving me exceptions? Is it not enforced to have Serializable?
Is it safe to continue this way or should I definitely implemente serializable?.
In which ones?, JPA2 Entities or PrimaryKey Classes?
Thanks a lot for the help.
JPA specification contains such a requirement (JSR-317 secion 2.4 Primary Keys and Entity Identity):
The primary key class must be serializable.
If EclipseLink really doesn't enforce this requirement, it's an implementation detail of EclipseLink and I wouldn't recommend you to rely on it.
However, there are no requirements on serializability of entities, except for the following one which looks more like a recommendation than a requirement:
If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the
entity class must implement the Serializable interface.
Nothing is required to be serializable, but it seems it is requried by the spec (10x to axtavt) for primary keys, although there is no direct need for it.
Serialization is needed if the objects are transferred over-the-wire or persisted to disk, so I can't see the reason behind that decision. However, you should conform to it.
Primary key classes have to implement serializable and composite-ID class must implement serializable are two different questions.
I am going to answer you both, and hope it will help you to distinguish and understand holistically.
Primary key classes have to implement serializable:
Note: It could work without its iplementation also.
JPA specification contains such a requirement (JSR-317 secion 2.4 Primary Keys and Entity Identity):
The primary key class must be serializable.
However, there are no requirements on serializability of entities, so it's a recommendation than a requirement
exception:
If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the Serializable interface.
Composite-ID class must implement serializable.
The id is used as a key to index loaded objects in the session.
The session object needs to be serializable, hence all objects referenced by it must be serializable as well.
In case of CompositeIds the class itself is used as the id.