JPA entity for a table without primary key - java

I have a MySQL table without primary key, and I have to map it into a JPA entity. I cannot modify the table in any way.
Because entities must have a primary key, I have to specify one. If I'm certain that the field I use as a primary key in the entity (or the fields, should I opt for using composite primary key) will always be unique (and not null) in table, can the fact that the table doesn't have a primary key specified in CREATE TABLE cause any issues?

That's correct. JPA has no way of knowing if the column(s) it is using as a PK is actually a real PK in the database. If those column(s) are, in practice, a PK, then it should be fine.
You may potentially get some performance problems if the pseudo-PK columns are not correctly indexed, though - JPA will execute queries against the PK on the assumption that it will perform well.

JPA itself doesn't analyze your database. Just don't use common methods using primary key (find/merge/...) instead use named queries, for example using jpql update syntax.
#Entity
#Table(name = "login")
#NamedQueries({
#NamedQuery(name = "Login.updateLastOnline",
query = "UPDATE Login l SET l.lastOnline = :newDate WHERE l.loginId = :loginId")
})
public class Login implements Serializable
{
It doesn't matter if loginId is primary key

Related

Repetition of constraint in liquidbase and entity definition

I`ve noticed that in my project some composite constraint are set in a liquidbase,
for example
constraint importer_ukey unique (name, country_id, is_importer, is_manufacturer)
but then they are repeated in entity definition in #Table annotation
#Table(uniqueConstraints = {#UniqueConstraint(name = "importer_ukey",
columnNames = {"name", "country_id", "is_importer", "is_manufacturer"})})
Is there any positive in repetition of uniqueConstraint in entity ?
Other than for creating the schema based on the JPA annotations, it is also a needed at runtime for the JPA provider to order INSERT, UPDATE and DELETE statements correctly.
Unique constraints ensure that the data in a column or combination of columns is unique for each row. A table's primary key, for example, functions as an implicit unique constraint. In JPA, you represent other unique constraints with an array of UniqueConstraint annotations within the table annotation. The unique constraints you define are used during table creation to generate the proper database constraints, and may also be used at runtime to order INSERT, UPDATE , and DELETE statements. For example, suppose there is a unique constraint on the columns of field F. In the same transaction, you remove an object A and persist a new object B, both with the same F value. The JPA runtime must ensure that the SQL deleting A is sent to the database before the SQL inserting B to avoid a unique constraint violation.
Source: https://openjpa.apache.org/builds/1.0.2/apache-openjpa-1.0.2/docs/manual/jpa_overview_mapping_unq.html
So yes: it is important.

Persistent entity '*******' should have primary key error in #Entity class

When creating an #Entity mapping a table my IDE notifies me: Persistent entity '*******' should have primary key.
But the table in the DB doesn't have an ID (I think it's bad but it's legacy which I've no permissions to fix)
What should I do? Will it work if I just omit the ID field? Or should I make up an ID which is not mapped on the table but satisfy the code?
Every JPA entity must have a primary key.
You can find the documentation here.
From the Java Persistence book: Identity and Sequencing: here
If your object does not have an id, but its table does, this is fine.
Make the object an Embeddable object, embeddable objects do not have
ids. You will need a Entity that contains this Embeddable to persist
and query it.
Try also to read the answers here

Hibernate One To Many Mapping With Fixed Values

I don't have a lot of experience with database design and i try to understand the general logic behind it with using an ORM like hibernate. I have two tables user and languages. User could know one or more languages so there is a one to many relation between two tables. But i have a fixed length of languages English , Spanish and French for example. As i understand with each new user instance persisted there will be duplicate entries in the language table with a foreign key of that person. Is there a way to prevent this duplicate entries ?
Your understanding is a little confused. You can map a OneToMany relationship using a Foreign Key, and there are good database reasons to do so, though generally a JPA provider recommends against it. However, you are describing a ManyToMany relationship. A User will (or could) have many Languages. A Language will have many Users. When you create a many to many relationship with annotations:
#Entity
public class Person {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany
private List<Language> languages;
and
#Entity
public class Language {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
The JPA provider will create an association or Join Table, with an id from each Entity in it:
create table Person_Language (Person_id bigint not null, languages_id bigint not null)
When you create a language, an entry will be put in the language table. When you create a user, an entry will be put into the user table. When you add a language to a person's languages then an entry will be put into the Join Table.
insert into Person_Language (Person_id, languages_id) values (?, ?)
There will be only unique combinations of Person_id and languages_id in the join table, and so the database will be well normalized. You would not be able to assign a language to multiple users using a Foreign Key in the Language entity for the reason you pointed out: there would be only one foreign key column for any given language.

POJO data with one to many / many to one relationship(JDBC)

For example I have two entities : Enterprise, Department. Enterprise has many departments, department has one enterprise, so there is a column - Enterprise_ID in Department table.
I have a function for saving Department object
void save(Department department);
To add Enterprise_ID in the table I need to have either reference on Enterprise object or enterprise's id.
Which way is more suitable?
However I prefer do not have such information in department object but on this way how can I save Enterprise_ID in the table ? It seems to me Hibernate somehow doing it.
public class Department{
private long id;
private String name;
private DepartmentType type;
private List<Employee> employees;
//getters()/setters()
}
public class Enterprise{
...
private List<Department> departments;
...
}
Department does not have any information about Enterprise in which it exists. So using only department object I can't insert Enterprise_ID(FK) in department table. But hibernate's save method somehow doing it. How can I do it without hibernate using entities above;
I use JDBC.
To do it the same way as hibernate does, you would have a save(Enterprise) method that would persist the enterprise object to the db and also insert/update the foreign key association.
Hibernate supports both nullable and non-nullable foreign key. In the latter case, it will first insert the enterprise, obtaining its primary key value, and then insert the department's along with the correct foreign key value.
You could do the same. But the save(Department) method would only be able to do updates on the department table and not change the association to the enterprise table. To do that, you would have to change the collection in enterprise and save/update that to the db.
Hibernate will only save/update the foreign key if you change something in the Enterprise.departments collection. It's the only way to do it if you don't have the reverse relation.
In your code, you'll have to use the Enterprise object to update the foreign keys in the Department table.
You could create a bidirectional association, by putting a field 'enterprise' in your Department class, but then you need to keep both relations in synch manually...

CRUD operation using Hibernate on table without Primary key [duplicate]

I making a sample application with Hibernate. My requirement is that there is no primary key on the table. I had to do only select query from application. I know there should be a primary key, but the table I am referring has been made without it.
It has about 50k records. So, modifying the table to add ID column does not see viable option.
Can it possible?
Hibernate requires that entity tables have primary keys. End of story.
50k records is simply not that many when you're talking about a database.
My advice: add an autoincrement integer PK column to the table. You'll be surprised at how fast it is.
So, modifying the table to add ID column does not see viable option.
Why's that? Do you just mean, because it already has fifty thousand records? Trust me, that's really not very many.
Even if the table doesn't have a surrogate key, and doesn't have a primary-key constraint, and even if you're not willing to alter the table, it still probably has some sort of candidate key — that is, some set of columns that are never null, and whose values uniquely identify a record. Even without altering the table to enforce their uniqueness and non-nullity, you can tell Hibernate that those columns form a composite ID.
I have found solution for tables without primary key and null as values. It will work on oracle DB. Maybe something similar exists for other DBs.
You should create new primary key in the POJO class:
#Id
#Column(name="id")
private Integer id;
and use createNativeQuery like this
getEntityManager().createNativeQuery("select rownum as id, .....
The native query will generate primary key and you will get unique results.
Not with Hibernate. It requires a primary key.
Using DB2 with a table without primary keys the following works:
Define the primary key field in the Entity similar to:
#Id
#Column(name="id")
private Integer id;
For Select Query add:
String selectQuery = "select ROW_NUMBER() OVER () id, ..."
I haven't tested with updates to the entity but selecting the info from the DB works fine

Categories