Hibernate - Recreating a table and assign primary key from one(beginning) - java

I am working with PostgreSQL database for a Spring RESTful API. I am using Spring Data, Spring JPA and Hibernate.
To produce a customized primary key, I am using SequenceGenerator. Everything works fine. The problem occurs when I am deleting a table from database and want create it again where the primary key will be again start from 1.
I am deleting a table from database for some reason which will be created again. I am using pgAdmin UI where I am just dropping the table. Next time when I am creating the table again, Hibernate still remembers the last produced primary keys and thus it start producing primary keys from the next number of the last primary key, thus producing a totally different not 1 which I want. I think the reason is, hibernate is storing the record of last produced primary keys though the table has been deleted.
That's why I am looking for help how to force hibernate to start producing primary from from 1 (one) for a newly created table.
In property file, I have the following property:
spring.jpa.hibernate.ddl-auto=update
I tried to by setting the following,
spring.jpa.hibernate.ddl-auto=create
It solved the problem for this table but rest all of tables were also recreated, thus I lost all my data.
This are class for which I am trying to recreate a table.
#Data
#Entity
#Table(name = "professions")
public class Profession extends BasicEntity {
#Id
#Column(name = "profession_id", unique = true)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "profession_key_generator")
#SequenceGenerator(name = "profession_key_generator", allocationSize = 1)
private int profession_id;
#Column(name = "profession_rus_title", unique = true)
private String rusTitle;
#Column(name = "profession_eng_title", unique = true)
private String engTitle;
#Override
public Integer getId() {
return profession_id;
}
public Profession(String rusTitle, String engTitle){
this.rusTitle = rusTitle;
this.engTitle = engTitle;
}
public Profession(){
}
}

Related

Errors when changing MySql for PostgreSQL in Java with Hibernate App

I try to migreate my app from MySql to PostgreSQL. It just a very small app in which I'm working on. Just 5 or 6 tables.
So I recreate the same database in postgresql, I learnt that the user word is reserved for postgress and that the Primary Key needs to be Serial type.
So after some minor adjustment, Hibernate was working I can recreate the models directly from the db.
The first Issue that I have is that when I try to store something it added 0 as PK. So as in Java a "null" int is 0 (or let say, an unassign int is 0) when I get that object from the database (which PK is 0) and I'm creating a new object, it give me the error:
A different object with the same identifier value was already associated with the session
This is how I stored the entities.
public Object addOrUpdate(Object item) throws Exception {
sessionFactory.getCurrentSession().saveOrUpdate(item);
return item;
}
After some google, I change saveOrUpdate for merge, but although I didn't get that error, all the values where replacing the the first one (which has PK 0). So I di end in the database the last object was the one that was stored.
This is my table:
The id (the last column) was created as BigSerial.
And this is the model in Java created by Hibernate from my postgresql
#Id
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
I'm using Java1.8 and PostgreSQL 10.
So how I can keep using postgresql but avoid having those issues?
You need to add additional annotation if you want support auto increment in hibernate.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private int id;
The generated value annotation is required to auto increment the values.
There are four different types of generation strategies.
1) GenerationType.AUTO
2) GenerationType.IDENTITY
3) GenerationType.SEQUENCE
4) GenerationType.TABLE
Refer to the following link for explanation
https://thoughts-on-java.org/jpa-generate-primary-keys/

#GeneratedValue ID try to duplicate primary key of entry in existing database MySQL Java

I've created database of parts in MySQL by importing data from .xlsx file. Last part ID is 3717.
Now I want to insert new record with ID: 3718 into database from my webapp where ID is autogenerated, but the #GeneratedValue annotation tries to generate ID from '1' and then it throws org.springframework.dao.DataIntegrityViolationException for duplicating primary key.
How do I autogenerate IDs starting from the last part ID in the database?
#Entity
#Table(name = "parts")
public class Part {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private Integer quantity;
private Double price;
public Part() {}
//getters and setters
It depends on your hibernate version. Depending on that the generationtyoe.auto will trigger one thing or another.
If what is being used is a table sequence, it is enough with you manually executing sql statement to set current value to your desired one.
If what is being used is an auto_increment table column it is enough altering table to update current increment value.

Sequence used to increment and ID in Postgresql not called by hibernate

I added a sequence MAIL_ID_SEQ to an existing table in Postgresql :
CREATE SEQUENCE MAIL_ID_SEQ START WITH 1;
alter table MAIL alter column ID set default nextval('MAIL_ID_SEQ'::regclass);
alter SEQUENCE MAIL_ID_SEQ owned by MAIL.ID;
The ID exist inside a composite key MailId :
#Embeddable
public class MailId implements Serializable{
#Column(name = "ID")
private int id;
#Column(name = "YEAR")
private int year;
}
I want the ID to be auto_increment using the sequence I created.
The problem is that the value of the ID is always 0 when a new record is inserted from via Hibernate, but when I insert a value directly from the command line (inset into MAIL ..) in the MAIL table, the value of the ID is incremented.
You need to add annotations like this to the id field:
#SequenceGenerator(name = "mail_id_gen", sequenceName = "MAIL_ID_SEQ", allocationSize = 1)
#GeneratedValue(generator = "mail_id_gen")
The generator name must be different for each class. The allocationSize is completely optional, but setting it to 1 is a workaround to a bug in Hibernate 5.0 and 5.1 related to sequences not created by schema export. Another workaround for that bug is to set the hibernate.id.optimizer.pooled.preferred property to NONE in the persistence.xml like this:
<property name="hibernate.id.optimizer.pooled.preferred" value="NONE"/>
If this is not enough and it still tries to insert 0, change the field type from int to Integer and leave it's default to null.

Hibernate Exception: Missing Column (column exists)

Okay, so within the database we have a table called distributionCompanies, created like so:
CREATE TABLE `distributionCompanies` (
`distributionCompanyID` INT(11) NOT NULL,
`distributionCompanyName` VARCHAR(255) NOT NULL,
PRIMARY KEY (distributionCompanyID)
);
I'm trying to map this table to a class using Hibernate:
#Entity
#Table(name = "distributionCompanies")
public class DistributionCompany implements DatabaseObject {
#Id
#GeneratedValue
#Column(name = "distributionCompanyID", length = 11, unique = true, nullable = false)
private int distributionCompanyID;
....
However, when running, I hit this issue:
Initial SessionFactory creation failedorg.hibernate.HibernateException: Missing column: distributionCompanyID_distributionCompanyID in database2.distributionCompanies
This isn't the only table in the database, and I've managed to map other classes successfully using the same method, so I'm a little stumped as to why this is causing an issue.
Thank you for your time,
Samuel Smith
EDIT: In response to Xavi's comment, I temporarily removed another mapping for the column, and the error went away, so the bad-egg probably lays in the following code:
#ManyToOne(targetEntity = DistributionCompany.class)
#JoinTable(name = "distributionCompanies", joinColumns = { #JoinColumn(name = "distributionCompanyID", nullable = false) })
private int distributionCompanyID;
Hibernate is looking for a column named distributionCompanyID_distributionCompanyID in your distributionCompanies table.
This is probably due to a ToOne association mapping towards this table without #JoinColum.
From Hibernate Documentation:
The #JoinColumn attribute is optional, the default value(s) is like in one to one, the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column in the owned side. In this example company_id because the property name is company and the column id of Company is id.
If you've got a #ManyToOne or #OneToOne association mapping in another entity, this would explain why Hibernate is looking for such a column.
EDIT Seeing the association mapping you posted, it looks like it should be:
#ManyToOne(targetEntity = DistributionCompany.class)
#JoinColumn(name = "distributionCompanyID")
private DistributionCompany distributionCompany;
The #JoinTable annotation is used to specify a join table (that means an intermediate table used to model many-to-many associations). And the point of mapping an association would be to dispose of the mapped object instance (in this case a DistributionCompany, not just a distributionCompanyId).

Native Query (JPA ) not reset and return the same old result

I have a native sql query as the following :
for (init i=0; i<=2 ; i++) {
String sql = "Select * from accounts where id = ?";
Query query = em.createNativeQuery(sql,AccountBean.class);
query.setParameter(1, i );
AccountBean accountBean = (AccountBean)query.getSingleResult();
}
For the first loop it works correctly but any loop after the first one returns the same result as the first one , i debug it, the parameter changed , it works correctly if i change
Query query = em.createNativeQuery(sql,AccountBean.class);
to
Query query = em.createNativeQuery(queryString);
Regards
Wish79
Every JPA entity must have a primary key. Your JPA entities may not properly reflect the primary key, if any, on the database table.
I ran into the same problem. In my model class I had only one class variable annotated with #Id. However, that was not an accurate reflection of the table itself, which has a composite primary key. Thus, my query results returned the correct number of rows, but each confoundingly contained the same values, even though the actual data was different in the db. For example, this query:
Query query = entityManager.createQuery
("SELECT tbl FROM Tbl tbl WHERE tbl.id = 100
and tbl.code in ('A','B','C')");
...returned 10 rows, each showing a code of 'A'. But in actuality 9 of those 10 rows had a different code value ('B' or 'C'). It seemed as if the results were being cached and/or the tbl.code predicate was ignored. (That happened whether I used JPQL or Native SQL.) Very confusing.
To fix this I added an additional #Id annotation to my model to reflect the composite primary key:
#Id
#Column(name = "Code")
public String getCode() {
return this.code;
}
Now the query returns the data correctly and the code select criteria is no longer effectively ignored.
Edit: Although the above worked for me, on further research it seems a better approach to configure a separate JPA Entity composite primary key class. See http://docs.oracle.com/cd/E16439_01/doc.1013/e13981/cmp30cfg001.htm.
For example, here's an Entity class with an embedded primary key (see #EmbeddedId):
/**
* The persistent class for the SOME_TABLE database table.
*/
#Entity
#Table(name = "SOME_TABLE")
public class SomeTable implements Serializable {
#EmbeddedId
private SomeTablePk id;
#Column(name = "NUMBER_HRS")
private BigDecimal numberHrs;
...
...and here's the composite primary key class (see #Embeddable):
#Embeddable
public class SomeTablePk implements Serializable {
#Column(name = "SOME_ID")
private String someId;
#Column(name = "ANOTHER_ID")
private BigDecimal anotherId;
public String getSomeId() {
return someId;
}
...

Categories

Resources