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

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

Related

CockroachDB SERIAL field not working with JPA IDENTITY Strategy

I'm migrating an app to use CockroachDB and we are using the GeneratedValue mapping in Java with SERIAL type columns to manage primary keys.
id SERIAL PRIMARY KEY -- SQL
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY) -- Java JPA
We are getting the following error
ERROR: currval(): relation "scm_supply_centers_id_seq" does not exist
We dug a little and found out that it's because of PostgreSQL Dialect trying to get the last id inserted in as you can see in this link
PostgreSQL81IdentityColumnSupport
How can I find a workaround for this issue?
The SERIAL type is not backed by a sequence in CockroachDB. In order to use a SEQUENCE you need to explicitly create it and use the nextval() function as the DEFAULT value for the column. For example,
CREATE SEQUENCE customer_seq;
CREATE TABLE customer_list (
id INT PRIMARY KEY DEFAULT nextval('customer_seq'),
customer string,
address string
);
Note that there are performance implications to using SEQUENCE vs SERIAL due to the additional synchronization and communication requirements. See https://www.cockroachlabs.com/docs/stable/create-sequence.html for more details.
The above doesn't exactly answer your question, though. I don't know how you would use an explicit sequence from Hibernate.

why does this example for using Hibernate with `Set` fields not declare foreign key in the database table?

This link gives an example of how to use Hibernate with classes with Set fields.
The following is the part for defining the corresponding database tables in MySQL:
Define RDBMS Tables Consider a situation where we need to store our
employee records in EMPLOYEE table, which would have the following
structure −
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
Further, assume each employee can have one or more certificate
associated with him/her. So, we will store certificate related
information in a separate table having the following structure −
create table CERTIFICATE (
id INT NOT NULL auto_increment,
certificate_name VARCHAR(30) default NULL,
employee_id INT default NULL,
PRIMARY KEY (id)
);
There will be one-to-many relationship between EMPLOYEE and
CERTIFICATE objects
I was wondering why it does not declare employee_id of CERTIFICATE as a foreign key to the primary key id of table EMPLOYEE in MySQL?
Thanks.
Normally, applications that use an Object-Relationship Mapping (ORM) framework, such as hibernate, handle all the relationship logic themselves (i.e. cardinality, constraints, ect..). So it is possible that, as far as the database concerns, employee_id is just a single number that has no relationship with any other table, and, on the other hand, Hibernate considers it as a foreign key to the Employee table. In this case, Hibernate would be the one in charge of managing all the relationship logic.
The advantage of this approach is that you can create certificates that are not associated to any employees at the database level. Let's say that you are migrating data to a database, and you migrate first all the certificate's table. If you had enforced the foreign key constraint, you couldn't do that: you would have to first migrate the employees' table and THEN the certificates one. However, by following the tutorial on the link you posted, you wouldn't need to worry about this, because you can have certificates belonging "fake" employees. This would happen in an intermediate transient state when you're not done migrating all your data.

jpa when insert row should return the sequence number used for primary key column

I know in sql(oracle) we can use "retruning into" but is there something which can be automated using JPA when using em.create().
Try em.merge(), it returns the attached instance you just persisted. You might have to em.flush() before you see the generated primary key.

Need to put #Index even when I marked with #Column(unique=true)?

Need to put #Index even when I marked with #Column(unique=true) ?
I have a property that will be used frequently to retrieve the entity and wanted to make it an index column on the database. So this property is already marked with #Column(unique=true), do I need to put #Index?
thanks
Most databases do implement UNIQUE constraints using a UNIQUE INDEX, but they aren't required to and a UNIQUE constraint does not necessarily give you the benefits of an index. In theory, a constraint would not be considered by the query planner whereas an index would be.
That said, in the particular case of MySQL, it seems that a UNIQUE constraint and a UNIQUE INDEX are "synonymous".
But you should confirm that by checking the query plan.
I presume you are using mysql as the question is tagged with mysql
If you are using annotations and something like this
#Column(unique = true)
Then this gets converted to the following DDL by hibernate
unique (user_id)
When you query the mysql db and do
show index from
It would show user_id as an indexed field, so the answer is #unique is enough for the field to be indexed
HTH

JPA entity for a table without primary key

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

Categories