generate value in overrided attribute - java

I have class for ID
#org.hibernate.annotations.AccessType("property")
public class ObjectID implements java.io.Serializable
{
private long value;
long getValue()
{
return value;
}
void setValue(Long id)
{
value = id != null ? id : 0L;
}
// equals, hash, contructor
}
And have mapped class (Patient) that used this ID-class. I want generate long value in ObjectID class. help me.
I tried
public class Patient implements Serializable
{
#javax.persistence.Id
#javax.persistence.Column(name = "aa_id")
#org.hibernate.annotations.Formula("case when aa_id is null then patient_seq.nextval else aa_id end")
#javax.persistence.AttributeOverride(name = "value", column = #Column(name = "aa_id"))
private ObjectID id;
}
and
public class Patient implements Serializable
{
#javax.persistence.Id
#javax.persistence.SequenceGenerator(name = "PatientSequenceGenerator",
sequenceName = "patient_seq")
#javax.persistence.GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "PatientSequenceGenerator")
#javax.persistence.AttributeOverride(name = "value", column = #Column(name = "aa_id"))
private ObjectID id;
}
But there are not helpful
One of resolves of this situation is to write custom userType for ObjectID and write custom ID-generator.

compositeIds are normally assigned by the program and i do not know if there is even a possibility to set it (or parts of it) through a databasesequence out of the box.
first you could try to set it this way to see if it works:
public class Patient implements Serializable
{
#Id
#SequenceGenerator(name = "PatientSequenceGenerator", sequenceName = "lab_patient_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PatientSequenceGenerator")
private Long id;
}

Related

Spring data JPA saveAndFlush and cannot get auto increment field

I have object with #Id (primary key) and this is some business UIID field and I want another Long technical Id for some reasons but when saving the object I get null from getObjectId field:
#Id
private String id;
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
I have this storage class:
interface MyObjectStorage extends JpaRepository<MyObject, String>
And this is how I save it:
final MyObject saved = storage.saveAndFlush(toSave);
saved.objectId is null here..
And in my MySQL db the objectId field is marked not null auto increment..
PS. And I don't want this objectId field to be used by JPA when findById is executed.
Hibernate/JPA isn't able to automatically create a value for your non-id-properties. The #GeneratedValue annotation is only used in conjunction with #Id to create auto-numbers.
The solution (or work-around) suggested in this forum is to create a separate entity with a generated Id, something like this:
#Entity
public class GeneralSequenceNumber {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
}
#Entity
public class MyEntity {
#Id ..
private Long id;
#OneToOne(...)
private GeneralSequnceNumber myVal;
}
try the following code
#Id must be a type of Integer or Long
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
private String id;
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
interface MyObjectStorage extends JpaRepository<MyObject, Long>

JPA Hibernate - Insert with given ID, not with sequence

I´m refactoring a system to use Spring Boot/JPA/Hibernate.
There is a routine where the clients instances receive a list of objects from the central server to save. Each object from the list has an ID generated by the central server and I have to use the same ID when inserting on my clients instances, but this ID on my entity is an Autoincrement field.
My Entity:
#Entity
#Table(name = "usuario", schema = "adm")
#SequenceGenerator(name="seq_usuario_generator", sequenceName = "adm.seq_usuario", allocationSize=1)
public class UsuarioEntity implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_usuario_generator")
#Column(name = "id_usuario", unique = true, nullable = false)
private int id;
#Column(name = "name", length = 50)
private String name;
#Column(name = "active")
private Boolean active;
// getter and setter ommited
....
}
Should have something like this:
...
UsuarioEntity user = new UsuarioEntity();
user.setId(idFromCentralServer);
user.setName("Testing insert with given ID");
usuarioRepo.save(user);
...
When I execute this code, the given ID is ignored and a new one is generated from the local sequence.
Is there any way to save an object where I can set an ID without getting it from my sequence?
I still need to have the autoincrement feature, when the given ID is not provided.
Maybe this is not the most elegant solution I could end up with, but it solved my problem for now.
I created a custom sequence generator as follows:
public class CustomSequenceGenerator extends SequenceStyleGenerator implements Configurable {
private String sequenceCallSyntax;
#Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
sequenceCallSyntax = "SELECT nextval('" + params.getProperty("sequence_name") + "')";
super.configure(type, params, serviceRegistry);
}
#Override
public Serializable generate(SessionImplementor s, Object obj) {
Serializable id = s.getEntityPersister(null, obj).getClassMetadata().getIdentifier(obj, s);
if (id != null && Integer.valueOf(id.toString()) > 0) {
return id;
} else {
Integer seqValue = ((Number) Session.class.cast(s)
.createSQLQuery(sequenceCallSyntax)
.uniqueResult()).intValue();
return seqValue;
}
}
}
And my entity got like this:
#Entity
#Table(name = "usuario", schema = "adm")
#GenericGenerator(name = "CustomSequenceGenerator",
strategy = "<....my_package...>.CustomSequenceGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "adm.seq_usuario")
})
public class UsuarioEntity implements java.io.Serializable {
#Id
#GeneratedValue(generator = "CustomSequenceGenerator", strategy = GenerationType.SEQUENCE)
#Column(name = "id_usuario", unique = true, nullable = false)
private int id;
#Column(name = "name", length = 50)
private String name;
#Column(name = "active")
private Boolean active;
// getter and setter ommited
....
}
This way, when I save an entity with ID as null on my service, the generator returns the nextval from my sequence, and if I set an ID that was given by the central server it gets inserted in my table correctly.
If there is some more elegant solution, please let me know to update this answer.
Simply remove the #GeneratedValue annotation
#Id
#Column(name = "id_usuario", unique = true, nullable = false)
private int id;

How override getter of id column in jpa configuration [duplicate]

This question already has answers here:
Hibernate : How override an attribute from mapped super class
(2 answers)
Closed 5 years ago.
I have a problem for #Id in JPA that is described as follow?
There is a generic class as follow?
#MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
private static final long serialVersionUID = 4295229462159851306L;
private T id;
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
}
There is another class that extends from it as follow?
#Entity
#Table(name = "DOC_CHANGE_CODE" )
public class ChangeCode extends BaseEntity<Long> {
#Id
#GeneratedValue(generator = "sequence_db", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "sequence_db", sequenceName = "SEQ_DOC_CHANGE_CODE", allocationSize = 1)
public Long getId () {
return super.getId();
}
}
Because any sub class has its own sequence, I must specific any subclass #Id, because of that I override the its getter and put some annotations in top of that. Unfortunately it does not work correctly.
How do I fix problem and get my goal?
Try this:
#Entity
#Table(name = "DOC_CHANGE_CODE" )
#SequenceGenerator(name = "sequence_db", sequenceName = "SEQ_DOC_CHANGE_CODE", allocationSize = 1)
#AttributeOverride(name = "id", column = #Column(name = "ID"))
public class ChangeCode extends BaseEntity<Long> {
#Override
#Id
#GeneratedValue(generator = "sequence_db", strategy = GenerationType.SEQUENCE)
public Long getId() {
return id;
}
}
It's not possible to override the #Id from a base class.
The only way to do it is to provide your own custom IentifierGenerator and provide a different logic based on the subclass (e.g. using a sequence name based on the subclass name).
That's why adding the #Id attribute in the #MappedSuperclass only makes sense for the assigned generator or for IDENTITY.

What is the correct way to annotate a class with a foreign id using Hibernate?

I am working on converting an existing project over to use Hibernate. I have a class like this:
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Long userId;
#Column(name = "group_id_user")
private Long groupId;
#Column(name = "name")
private String name;
...
// getters and setters....
}
and a class like this:
#Entity
#Table(name = "group")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private Long groupId;
#Column(name="group_name")
private String groupName;
...
// getters and setters....
}
The column named "group_id_user" in the user table is supposed to be a foreign key to the column named "group_id" in the group table.
Is it okay or "correct" to have the classes structured as shown above or should they be structured as shown below to make sure that the foreign key exists in the Database?
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Long userId;
#ManyToOne
#JoinColumn(name = "group_id_user")
private Group group;
#Column(name = "name")
private String name;
...
// getters and setters....
}
and
#Entity
#Table(name = "group")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private Long groupId;
#Column(name="group_name")
private String groupName;
...
// getters and setters....
}
I have tried using both formats but have had issues both ways. When I use the first format I have issues with the HQL syntax for joins while creating queries. When I try the second format I have issues with fetching just a User from the database without a Group, or adding a new User from a json object the has a groupId instead of a Group object. So before I spend anymore time switching back and forth between the two formats I want to know for sure which way should I be using the annotations to best fit industry standard?
I would try something like this if you could change the name of the columns too:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY) //This means you will need the database to generate the ids, if you are using Oracle this won't work. You would need to use SEQUENCE.
private Long id;
#ManyToOne
#JoinColumn(name = "group_id") //There will be no need to specify the join column if you use group_id.
private Group group;
#Column(name = "name")
private String name;
...
// getters and setters....
}
#Entity
#Table(name = "groups")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="group_name")
private String groupName;
...
// getters and setters....
}
Also if you can I would change the name of the tables to plural.
Also I use something that helps me a lot. I have a super class called "Identifiable" which just has the id and it looks like this:
#MappedSuperclass
public class Identifiable implements Serializable {
private static final long serialVersionUID = -9027542469937539859L;
#Id
#Column(name = "ID")
#GeneratedValue
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Identifiable other = (Identifiable) obj;
if (id == null) {
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
With that you can extend all your classes with ids easily like:
#Entity
#Table(name = "users")
public class User extends Identifiable {
private static final long serialVersionUID = -90275424699375956859L;
#ManyToOne
#JoinColumn(name = "group_id") //There will be no need to specify the join column if you use group_id.
private Group group;
#Column(name = "name")
private String name;
...
// getters and setters....
}
However if you cannot change the names, let us know the issues you are having with the traces that are throwing and we might be able to help.
Thanks!

Composite ID and its generation in JPA

I want use custom class like ID
#javax.persistence.Embeddable
class ObjectID impements Serializable{
private Long value;
//setters, getters and other
}
Here is mapped class
#Entity
#IdClass(ObjectID.class)
public class Country implements Serializable
{
#Id
#AttributeOverride(name = "value", column = #Column(name = "id"))
#SequenceGenerator(name = "CountrySequenceGenerator",
sequenceName = "lab_country_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "CountryCountryGenerator")
private ObjectID value;
// setters, getters, fields
}
Doesn't work. Value wasn't generated. Any ideas, how can I generate ID for composite-id?
Id class has to be Serializable and implements hashCode and equals

Categories

Resources