JPA #ManyToOne with different datatypes - jpa

I have two old database tables, that i need to use with JPA.
TOUR VEHICLE
----------------------- ---------------------
Id NUMBER(10) VehicleNumber CHAR(3)
VehicleNumber NUMBER(3) LicensePlate CHAR(10)
In my JPA entities I want tu use a #ManyToOne relationship from TOUR to VEHICLE.
Vehicle Entity:
public class Vehicle {
#Id
#Column(length=3)
private String VehicleNumber;
...
Tour Entity:
public class Tour {
#Id
#Column(precision=3)
private BigDecimal Id;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="VehicleNumber", referencedColumn="VehicleNumber")
private Vehicle vehicle;
...
But this of course doesn't work since the one vehicle number is translatet to String and the other is translatet to a BigDecimal(precision=3).
So what can i do to join them? Non-numeric values should be ignored.
Thanks for any advice.

VehicleNumber in TOUR table is a number while in the other one is CHAR.
First you need to match the types (better not to try to hack the standards).
then for #Id put the column name not #Column(precision=3). so it should be:
public class Tour {
#Id
#Column(name = "Id")
private BigDecimal id;
...
}
and do the same for the other table.
Oh by the way, I suggest you to use Long for the Primary Key not BigDecimal unless you have to.
But for entities, you are ok to work with Long

Related

Open JPA for an element of type Array

We have a requirement to store the weekdays against a particular site. Below is the table structure. I couldn't able to map the text[] to the entity property. We are using the open JPA for the repository. Can someone suggest the solution to have String[] in Entity class.
Table :
'''
site(id int, name varchar(50), weekdays text[]);
'''
Entity Class:
'''
#Entity
public class Site {
#Id
private Long id;
#Column
private String name;
#Column
private String[] weekdays;
}
'''

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.

ManyToOne doing multiple queries to fetch records

I have two entities, and dept_id is the foreign key here.
public class Student implements Serializable {
...
#Id
#Column(name="id")
private Integer id;
#ManyToOne
#JoinColumn(name = "dept_id")
private Department department;
...
}
and
public class Department implements Serializable {
...
#Id
#Column(name="id")
private Integer id;
#Column(name = "name")
private String name;
...
}
Now I am doing the following JPQL where I have around 100 parameters inside in query:
select o from Student o where o.id in(1,2,7,9,15,16, ...)
When I see the JPA log, I found it is fetching 100 records from the Student by one query. After that it is doing 100 separate queries to fetch the Department for each Student. So far my understanding is the I/O operation should be slow. Is there any way so that it fetches everything by a single query?
I found this worked for me:
query.setHint("eclipselink.join-fetch", "o.department");
Also, I found this one is handy as it does not make any joining, but fetches the records separately in a bulk.
query.setHint("eclipselink.batch", "o.department");

Can I use more than one #Id annotation in an Entity?

I want to define a table where the entire record is the primary key. The table has two columns which are references to other entities.
#Entity
public class ProtoList implements Serializable {
#Id
#ManyToOne ProtoObject listID;
#Id
#OneToOne ProtoObject po;
ProtoObject is an entity whose #Id is a regular generated Long.
The resulting relational data structure is intended allow any ProtoObject to be associated with an arbitrarily long List (actually a Set) of ProtoObjects. So the two table columns are just two Longs, always unique.
Will this work or do I have to define an #IdClass or something else?
After some experimentation I discovered that it was indeed necessary to use an #IdClass annotation. What is interesting is that in the Entity itself I have the #ManyToOne and #OneToOne annotations to create relational links to ProtoObjects, but in the IdClass the corresponding fields are inferred from the ProtoObject's own ID field.
So the result is:
#Entity
#IdClass(ProtoListKey.class)
public class ProtoList implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne ProtoObject listID;
#Id
#OneToOne ProtoObject po;
And the key is:
public class ProtoListKey {
private Long listID;
private Long po;
The primary key of ProtoList is Long so this works. The entire record is the primary key which is what I wanted. Lesson learned.

Cannot change colum names in JPA Eclipselink

I'm having problems making #Column(name="example") working.
I've got a User class:
#Entity
public class User {
#Id
private String username;
....
}
A Role one:
#Entity
public class Role {
#Id
private String name;
....
}
That are in a ManyToMany relationship. So I created a RoleMembership:
#Entity
#IdClass(UserRolePK.class)
public class RoleMembership {
#Id
#ManyToOne
#PrimaryKeyJoinColumn(name="USERNAME")
private User user;
#Id
#ManyToOne
#PrimaryKeyJoinColumn(name="ROLE")
private Role role;
....
}
As you can see, the primary key is defined in UserRolePK:
public class UserRolePK{
#Id
#Column(name="ROLE")
private String role;
#Id
#Column(name="USERNAME")
private String user;
...
}
In this class I use #Column(name="USERNAME") and #Column(name="ROLE") to force its name to that string, but it's not working: JPA gives it the default names USER_USERNAME and ROLE_NAME (that are in TABLE_ID format).
Can anyone help me finding the mistake?
Thanks,
Andrea
EDIT:
I need to have three tables:
user (username (pk), password ....)
user_role (username, role_name)
role (name (pk), description)
I cannot change User definition in my model.
Remove all the annotations in UserRolePK and change your #PrimaryKeyJoinColumn annotations to #JoinColumn annotations.
Your usage of PrimaryKeyJoinColumn does not seem to make sense. I think you should be using just a #JoinColumn, or are you also mapping the columns as basics?
Perhaps include you complete class, and the DDL that is generated.