Change the Entity ID name in JPA - java

Could be possible change the name of the Entity variable ID in JPA? Currently, the DAO save method use the Entity ID.
We have multiple existing tables in our database and then, we will have to add the ID column to all tables. Is there any way I can avoid adding the fields?
I suppose one possibility will be to override the DAO methods, but any other ideas?
Thanks in advance.

So your entity is defined as:
#Entity
public class SomeEntity {
#Id
private Integer id;
//...
}
You don't have to name the variable id unless you really want to. You could name this someEntityId and JPA nor Hibernate cares. The only influence the property name will have is how the NamingStrategy implementation will map that to a column name in the database.
We can override the naming strategy and apply specific names to columns if we need where cases exist that the naming strategy doesn't work for us.
#Id
#Column(name = "some_entity_id")
private Integer id;
This essentially will map the id variable to a column named some_entity_id.
Hope that helps.

Related

How to save an entity without an id in Spring Data JPA (hibernate)

consider an entity with just an id and text field:
#lombok.Data
class Entity {
#javax.persistence.Id
UUID id;
String name;
}
consider that the table definition is as follows:
create table entity (
id uniqueidentifier not null primary key default newid(),
name varchar(max)
);
I am then curious why this doesn't work and how i could make it work:
UUID savedId = entityRepository.save(new Entity().setName("entity name")).getId();
In JPA, entity IDs can be either assigned by the application code, or generated (by the JPA provider, such as Hibernate, or by the database). In many situations, it's desirable to have the entity IDs be generated instead of applicaiton-assigned; it seems like that's what you are expecting.
If so, you need to annotate the id field with #GeneratedValue. For example:
class Entity {
#Id
#GeneratedValue
UUID id;
String name;
}
Note that there are considerations to be made regarding the generation strategy, so you'll want to educate yourself about them and make the right choice based on your situation. This is a good page that discusses the options. This SO Answer also is worth reading (the author is a well-known expert on JPA and Hibernate).

Can I create a entity mapping to table which has a name from specific property of the entity?

For example, I have an entity below.
#Entity
public class Indexer
#NotNull #Id
private long id;
#Column
private string volumeKey;
}
I want to create a table with a ‘volumeKey’ property in this entity.
For example, A indexer has a ‘X12372’ as a volumeKey of property. I want this entity to be mapped to ‘INDEXER_X12372’.
And I tried to create custom NamingStrategy class for Indexer. And I can’t get an entity to be mapped in this class for making a table of name from.
You want the table to be used to be determined by a value of a property.
This is not possible with JPA or Spring Data JPA.
But some (many?) databases can do this transparently with partitioned tables.
See https://docs.oracle.com/cd/B28359_01/server.111/b32024/partition.htm for Oracle documentation as an example.
It should be easy enough to find a similar document for the database you use.

Spring Data JPA get entity foreign key without causing the dependent entity lazy load

I have an #Entity A that references another entity B using OneToOne relation ship. I fetch entity A using spring data JpaRepository
A a = aRepository.findById(1);
int b_id = a.getB().getId();
As you can see I need to query ID of the B table, however in order to do that, I need to call getter of the B table, which will cause lazy-loading the B table itself. I do not want to do that because the only thing I need is the get ID, nothing else, and that ID is present in the first A table.
Is there any trick that will help me to get ID of the dependent table without triggering new query?
UPDATE
#Entity
class A {
#Id
private Long id;
#OneToOne
private B b;
}
#Entity
class {
#Id
private Long id;
}
Without looking at the entity mapping, I suspect, your entity classes might be using hibernate annotations on the field. With this if you call even the getId() method as in a.getB().getId() on the entity it will result in initializing the proxy (i.e., B object) and hits the database to fetch it.
So if the intent is only to get the id of the entity you can place the hibernate annotations on the getter methods instead. This doesn't result initializing the proxy (B object) to return the id. Although accessing any property other than id will result in hitting the database.
Have a look at related bug at HHH-3718
So, try using property/getter AccessType instead of field access. As an example instead of placing the annotations on field
#Id
#GeneratedValue(...)
private long id;
place them on the getters
#Id
#GeneratedValue(...)
public long getId() { ... }
Make sure you make similar changes to all the fields of B entity. Although you can explore #Access(AccessType.PROPERTY/FIELD) later.
There is already a related bug HHH-3718 regarding this behavior.
And a related topic on hibernate forum regarding field vs property access type that might be of interest for you Field Vs Property access
Posting your entities classes would help, if this doesn't resolve the issue.

ORA-00942: table or view does not exist - Hibernate with non-capital letters

I have the following error when I'm trying to map an entity:
ORA-00942: table or view does not exist
I figured out that the problem is that hibernate is trying to find the name of the table in "non-capital" (lowercase) letters, but Oracle has the tables names in capital letters (although the tables were created with non-capital letters).
I can fix the problem if I add the annotations #Table and #Column putting the names in capital letters, but I don't want to add those annotations.
I would like to know if there is any different way to do it.
Sql:
create table foo(
id integer not null
);
alter table foo
add constraint foo_pk
primary key (id);
Entity that is not working:
#Entity
public class Foo {
#Id
private Long id;
//getter and setter
}
Entity that is working:
#Entity
#Table(name = "FOO")
public class Foo {
#Id
private Long id;
//getter and setter
}
Thanks!
You can define a custom NamingStrategy, to make the specific table and column names translation from your entity to Database. Here is some example how to do it.
So, all you need is to create an implementation of NamingStrategy interface or extend some of existing strategies, modifying it's behaviour with the behaviour you want to get and then register this new strategy via hibernate XML configuration parameter hibernate.ejb.naming_strategy or via Configuration class.

Hibernate zeroToOne

I am trying to establish a relationship between 2 entities which would be zero-to-one. That is, the Parent can be saved without the associated Child entity and also along with the assoicated Child.
Following are the 2 Entity classes...
Employee (Parent)
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name="EMP_NAME")
private String name;
#PrimaryKeyJoinColumn
#OneToOne(cascade = {CascadeType.ALL})
private EmployeeInfo info;
#Column(name="EMP_ENUM")
private Integer enumId;
EmployeeInfo (Child)
public class EmployeeInfo {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="EMPLOYEE_EMAIL")
private String email;
With such kind of a relation and id column of the only Parent (Employee) table set to AUTO INCREMENT in MySql DB, the problem is that while saving a Parent->Child object graph, I get the following exception
org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access: SQLException for SQL [insert into EMP_INFO
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value
I tried setting the Child Table's Id property to AUTO INCREMENT in the DB , and the persistence of such a Parent->Child object graph is successful.
However, the problem described here surfaces, because I have a scenario in which I would like to save the parent (Employee) object without the associated EmpInfo object, and hence do NOT want to have AUTO INCREMENT on the Child's id column.
One solution could be not use the PrimaryKeyJoinColumn, but use a particular JoinColumn, but that adds an unnecessary column to my existing Table.
Has anyone come across such a problem? If yes, any pointers would be much helpful.
Finally, I got it working thanks to Pascal and some googling from my side. Apparently, I cannot use the Native key generator for such relationships where the parent can exist without the child (optional = true).
The thing that worked finally was the following, leaving me the downside of having to deal with Hibernate specific annotation (#GenericGenerator) and also having to make-do with bi-directional relationships instead of the unidirectional that I wanted.
Employee (Parent) class remains unchanged as above. It has AUTO INCREMENT on the Id column.
As for the child class (EmployeeInfo) it changed to the following, and again WITHOUT having the AUTO INCREMENT set on the Id column.
#Table(name="EMP_INFO")
#Entity
public class EmployeeInfo {
#Id
#GeneratedValue(generator="foreign")
#GenericGenerator(name="foreign", strategy = "foreign", parameters={
#Parameter(name="property", value="verifInfo")})
private Long id;
#OneToOne(optional=false)
#JoinColumn (name="id")
private Employee emp;
#Column(name="EMPLOYEE_EMAIL")
private String email;
This helped me achieve what I wanted but on the downside, GenericGenerator is not a JPA annotation, it is a hibernate annotation, and sadly I have to make do with that as of now because JPA does not currently support this(or any similar) annotation.
Anyway, it helps to get through such cases :-)
I have a scenario in which I would like to save the parent (Employee) object without the associated EmpInfo object.
The optional attribute of a OneToOne is true by default, which is what you want.
However, you are somehow misusing the #PrimaryKeyJoinColumn here (well, it actually depends on what you really want to achieve but your current combination of annotations is not correct).
IF you want to map a OneToOne with a shared primary-key, use the #PrimaryKeyJoinColumn. But in that case, don't use a GeneratedValue on EmployeeInfo and set the id manually or, if you don't want to set it manually, use the Hibernate specific foreign generator that I already mentioned in your previous question. Check also the related question mentioned below.
And IF you do not want to use a shared primary key (like in your current code since you're trying to get the id generated by the database), then do not use the PrimaryKeyJoinColumn.
You have to make a choice.
References
JPA 1.0 specification:
9.1.32 PrimaryKeyJoinColumn Annotation
Related question
JPA Hibernate One-to-One relationship.

Categories