Hibernate insert automatic number in a column - java

Hello brothers and sisters,
I have a class that keeps userAuthInformatin with authuserid column,username column, and authusertoken column.
I want to insert uuid number in authusertoken column with every insert. I learned about Generated(GenerationTime.INSERT) but i don't know exact way to do this.
package entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
#Entity
#Table(name = "authusers")
public class AuthUser {
#Id
#GeneratedValue
private int authuserid;
#Generated(GenerationTime.INSERT)
#Column(name = "authusertoken")
private long authusertoken;
#Column(name = "username")
private String username;
public int getAuthuserid() {
return authuserid;
}
public void setAuthuserid(int authuserid) {
this.authuserid = authuserid;
}
public long getAuthusertoken() {
return authusertoken;
}
public void setAuthusertoken(long authusertoken) {
this.authusertoken = authusertoken;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

You can simply use the UUID Java class and assign a value to this token field at object creation time:
#Column(name = "authusertoken", columnDefinition = "BINARY(16)")
private UUID authusertoken = UUID.randomUUID();
If the current associated row already has a value, when fetching the Entity, Hibernate will set it using Reflection and override the authusertoken with the row's column value.
If this is a new object, the authusertoken will get a default UUID when the object is instantiated.

Related

Problem while populating child's id with parent's id in Hibernate JPA

i'm not a professional in spring boot / hibernate jpa, so i apologize in advance.
I have 2 Entities, one called Document and the other called Bgo. Document is the parent table and Bgo the child. So my objective is to create the Document and after that, Bgo will receive it's id, for example:
When i create the first Document, it will have id_document = 1, so after that, the Bgo will have id_document = 1 as well.
I want to populate the child's id with the parent's id.
Here is the Parent Entity:
package com.testing.testing.models;
import java.io.Serializable;
import java.sql.Date;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id_document;
private int num_document;
private Date date;
#OneToOne(mappedBy = "document", cascade = CascadeType.ALL)
private Bgo bgo;
public Document() {
}
public Document(Bgo bgo) {
this.id_document = bgo.getId_document();
this.bgo = bgo;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Bgo getBgo() {
return bgo;
}
public void setBgo(Bgo bgo) {
this.bgo = bgo;
}
public long getId_document() {
return id_document;
}
public void setId_document(long id_document) {
this.id_document = id_document;
}
public int getNum_document() {
return num_document;
}
public void setNum_document(int num_document) {
this.num_document = num_document;
}
}
And Child Entity:
package com.testing.testing.models;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
#Entity
#Table(name = "BGO")
public class Bgo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long id_document;
private String name_bgo;
private int num_bgo;
#OneToOne
#PrimaryKeyJoinColumn(name = "id_document", referencedColumnName = "id_document")
private Document document;
public Bgo() {
}
public Bgo(Document document) {
this.id_document = document.getId_document();
this.document = document;
}
public long getId_document() {
return id_document;
}
public void setId_document(long id_document) {
this.id_document = id_document;
}
public String getName_bgo() {
return name_bgo;
}
public void setName_bgo(String name_bgo) {
this.name_bgo = name_bgo;
}
public int getNum_bgo() {
return num_bgo;
}
public void setNum_bgo(int num_bgo) {
this.num_bgo = num_bgo;
}
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
}
I used the term PrimaryKeyJoinColumn cause i want Bgo's id to be the Document's id, thats why i also used the same name "id_document". So Bgo's id will be Primary and Foreign at the same time (if it is wrong please tell me a better way to do it, knowledge is always welcoming)
I have also Document's Repository:
package com.testing.testing.repository;
import com.testing.testing.models.Document;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DocumentRepository extends JpaRepository<Document, Long> {
}
And Bgo's:
package com.testing.testing.repository;
import com.testing.testing.models.Bgo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BgoRepository extends JpaRepository<Bgo, Long> {
}
Document's Controller:
package com.testing.testing.controllers;
import java.util.List;
import com.testing.testing.models.Document;
import com.testing.testing.repository.DocumentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(value="/document")
public class DocumentController {
#Autowired
DocumentRepository documentRepository;
#GetMapping
public List<Document> listDocument() {
return documentRepository.findAll();
}
#PostMapping
public Document createDocument(#RequestBody Document document) {
return documentRepository.save(document);
}
}
Bgo's Controller:
package com.testing.testing.controllers;
import java.util.List;
import com.testing.testing.models.Bgo;
import com.testing.testing.repository.BgoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(value="/bgo")
public class BgoController {
#Autowired
BgoRepository bgoRepository;
#GetMapping
public List<Bgo> listBgo() {
return bgoRepository.findAll();
}
}
So basically, the problem is this:
enter image description here
When i create a new Document and also the Bgo object, Bgo's id is 0, as you can see in the image, the object Bgo has the "id_document = 0 ", shouldn't it be id_document = 1 ?
And when i try to list Bgo, it still shows id_document = 0:
enter image description here
That's how i want the database to be:
enter image description here
As you can see, they are different tables. But Document has the primary key and is the parent, and Bgo is a child cause it is receiving Document's id. As you can see, Bgo's has the Document's id, it is primary and foreign at the same time, thats why i used PrimaryKeyJoinColumn. Both of them have the same id, Document's id equals Bgo's id. So whenever i create a Document and a Bgo at the same time, both of them should have the same id.
you might need to use the inheritance functionality comes with Spring instead. have a look at this:
https://www.baeldung.com/hibernate-inheritance
you can for instance use the #Inheritance(strategy = InheritanceType.SINGLE_TABLE)
on your parent table. and then you will annotate the child with just the #Entity
and then you will extend it as you normally do in a normal Inheritance scenario
so your parent class will look like so:
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.Table;
import javax.persistence.InheritanceType;
#Entity
#Table(name = "Document")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Document {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private Integer Id;
#Column(name = "num_document")
private int num_document;
#Column(name = "date")
private Date date;
public Document() {
}
public Document( int num_document, Date date) {
super();
this.num_document = num_document;
this.date = date;
}
}
and the child will look like so
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "Bgo")
public class Bgo extends Document {
#Column(name = "name_bgo")
private String name_bgo;
#Column(name = "num_bgo")
private int num_bgo;
public Bgo(String name_bgo, int num_bgo) {
super();
this.name_bgo = name_bgo;
this.num_bgo = num_bgo;
}
public Bgo() {
super();
}
}
and you will have One JPARepository which looks like so;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DocumentRepository extends JpaRepository<Document, Integer> {
}
the result of this code, will generate one table in your database with one extra column dtype which will identify the record to be either Bgo or any other type you might need to add in the future. this is the idea behind inheritance anyway
I hope this helped
Here are the three different inheritance strategy you have using spring
Single mapping is the default mapping
And it uses #inheritance(strategy = InheritanceType.SINGLE_TABLE) annotation to the parent class
In this strategy, the parent class is a table and all its children will be specified in a discriminator column in the parent table. The column called dtype and it contain the name of the entity as a value.
Table per the class strategy is similar to the superclass strategy but the superclass is also an entity you need to avoid this one if you want to make so many join queries
Joined table strategy is used the same as above. In this strategy, the subclasses and the superclass will all be tables in the database, but the subclasses will not inherit the filed of the superclass, it is useful if we want to apply data integrity and null constrains on some field
for more details look here
https://thorben-janssen.com/complete-guide-inheritance-strategies-jpa-hibernate/
choose which one will suit your case and then you can use the implementation I provided in the first answer and you only need to change the this annotation
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)

How to make dynamic POJO class?

I am using Spring and Hibernate for CRUD operation of product table.
I have got model product.java
product model is defined as below:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "PRODUCT")
public class Product {
private long gtin;
private String brandname;
private String subbrandname;
private String functionalname;
#Id
#Column(name = "gtin",unique=true)
public long getGtin() {
return gtin;
}
public void setGtin(long gtin) {
this.gtin = gtin;
}
#Column(name = "brand_name")
public String getBrandName() {
return brandname;
}
#Column(name = "brand_name")
public void setBrandName(String brandname) {
this.brandname = brandname;
}
The question is that field and data type of table product could be changed as per user input. Therefore how can I make product model dynamic so that I don't need to change code of product model in future. The changes can be made based on user input from the forms.
Here, I am using programmatic configuration of hibernate sessionfactory.

hibernate criteria query creating multiple sql

I am facing a very strange issue with hibernate criteria in my application. Below mentioned in the snippet from my source code.
Entity Class
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
#Entity
#Table(name = "AIRPORT")
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Airport implements Serializable {
private static final long serialVersionUID = -7120581694566566178L;
private Long id;
private String countryCode;
private String countryName;
private String cityCode;
private String cityName;
private String airportCode;
private String airportName;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "COUNTRY_NAME")
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
#Column(name = "COUNTRY_CODE", length = 10)
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
#Column(name = "CITY_CODE", length = 25)
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
#Column(name = "CITY_NAME")
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
#Column(name = "AIRPORT_CODE", unique = true, length = 10)
public String getAirportCode() {
return airportCode;
}
public void setAirportCode(String airportCode) {
this.airportCode = airportCode;
}
#Column(name = "AIRPORT_NAME")
public String getAirportName() {
return airportName;
}
public void setAirportName(String airportName) {
this.airportName = airportName;
}
}
DAO Class
Criteria criteria = getSession().createCriteria(getTemplateClass());
criteria.addOrder(Order.asc("countryCode"));
criteria.addOrder(Order.asc("cityCode"));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setCacheable(true);
return (List<Airport>) criteria.list();
Generated SQL when starting application and querying result
Hibernate: select this_.ID as ID1_12_0_, this_.AIRPORT_CODE as AIRPORT_2_12_0_, this_.AIRPORT_NAME as AIRPORT_3_12_0_, this_.CITY_CODE as CITY_COD4_12_0_, this_.CITY_NAME as CITY_NAM5_12_0_, this_.COUNTRY_CODE as COUNTRY_6_12_0_, this_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT this_ order by this_.COUNTRY_CODE asc, this_.CITY_CODE asc
If I call same code again and suppose I have 1000 airports list then it executes below query for 1000 times. This behavior is quite strange.
Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
........
........
Even I am using ehcache and even the below line in my criteria.
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Any help would be greatly appreciated.
I can think of a few different reasons why this might be occuring:
Your entity has an association defined in it that is configured to eager join by default and you have also specified that the association use FetchMode.SELECT. (This is known as the N+1 Problem)
While the transaction is still open, you are interacting with an association of each Airport object that is set to lazy load. By interacting, I mean, you are using a getter to access the relation, forcing Hibernate to deproxy the associated entity. Since the deproxying is occurring with the transaction still open and the associated entity has not yet been loaded, Hibernate automatically fetches the association for you.
You have written your Airport entity's hashcode or equals methods to use a property of an association that is not eagerly joined and forces hibernate to deproxy, and thus fetch the unloaded entity, while within the transaction.

GenerationType.AUTO vs GenerationType.IDENTITY in hibernate

Currently, we are using MySQL as a database and we use
#Generated Value(strategy = GenerationType.IDENTITY)
It's working perfectly in certain situations we need to migrate our database to Oracle at that time it's not working properly. If anyone knows what's the actual difference is present behind this and how it's working?
Quoting Java Persistence/Identity and Sequencing:
Identity sequencing uses special IDENTITY columns in the database to allow the database to automatically assign an id to the object when its row is inserted. Identity columns are supported in many databases, such as MySQL, DB2, SQL Server, Sybase and Postgres. Oracle does not support IDENTITY columns but they can be simulated through using sequence objects and triggers.
so I prefer to use SEQUENCE instead
Sequence objects use special database objects to generate ids. Sequence objects are only supported in some databases, such as Oracle, DB2, and Postgres. Usually, a SEQUENCE object has a name, an INCREMENT, and other database object settings. Each time the .NEXTVAL is selected the sequence is incremented by the INCREMENT.
Example :
#Entity
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="EMP_SEQ")
#SequenceGenerator(name="EMP_SEQ", sequenceName="EMP_SEQ", allocationSize=100)
private long id;
...
}
How could it "work properly" (you don't define basic info like what you mean by that) with Oracle ? I don't see the relevance of AUTO to your question - that simply lets an implementation choose what it wants to use.
"IDENTITY" (as per JPA javadocs and spec - what you should be referring to) means autoincrement. There is no such concept in Oracle, yet there is in MySQL, SQLServer and a few others. I would expect any decent JPA implementation to flag an error when even trying such a thing.
Oracle would allow "SEQUENCE", or "TABLE" strategies to be used however
Im using JPA and Oracle 11g, the solution that worked for me is the following
package com.example.springsocial.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
#Entity
#Table(name = "rol", uniqueConstraints = {
#UniqueConstraint(columnNames = "name")
})
public class Rol {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="rol_sequence")
#SequenceGenerator(name="rol_sequence", sequenceName="rol_sequence", allocationSize=100)
private Long id;
#Column(nullable = false)
private String name;
private Date createdAt;
#Column(nullable = true)
private Date updatedAt;
#Column(nullable = true)
private Integer createdBy;
#Column(nullable = true)
private Integer updatedBy;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Integer getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Integer createdBy) {
this.createdBy = createdBy;
}
public Integer getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Integer updatedBy) {
this.updatedBy = updatedBy;
}
}

Hibernate persist error, id field is null

Hi im trying to do a persist but looks like if one of the atributes never was set but, just before do the persist I print the value and is set. I´m working with postgrest
My persist metod
public void saveText(Document document){
sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
System.out.println(document.getText());
System.out.println(document.getId());
try {
session.beginTransaction();
session.persist(document);
session.getTransaction().commit();
}
catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
}
}
My object to pesist
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import br.com.symsar.sysged.acessobd.AccesData;
#Entity
#ManagedBean
#SessionScoped
#Table(name = "documents", schema = "public")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "\"id\"")
private int id;
#Column(name = "\"text\"")
private String text;
public void persist() {
AccesData access = new AccesData();
access.saveText(this);
}
/**
* #return the text
*/
public String getText() {
return text;
}
/**
* #param text
* the text to set
*/
public void setText(String text) {
this.text = text;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
Sql query showed by hibernate
Hibernate: insert into public.documents ("id", "text") values (null, ?)
This is the error:
ERROR: ERRO: Null value in the column "id" violates not-null constraint
Field id have JPA annotation #Id in your entity class. It's mean's that it can't be null. Try insert value without id parameter:
Hibernate: insert into public.documents ("text") values (?)
Try removing annotations
#ManagedBean
#SessionScoped
I resolved not using session factory now I´m using entity manager, when I made this change works.
Thanks all for the ideas

Categories