How to avoid duplicate entries in Postgres database? Entries contain varying value - java

Method to store entity:
PoolDef poolDef = new PoolDef();
poolDef.setDate_from(date);
poolDef.setName(poolList.getPoolList().get(i).getName());
poolDefRepository.save(poolDef);
Entity itself:
#Setter
#Getter
#EqualsAndHashCode(of = {"Id"})
#Transactional
#Entity
public class PoolDef {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String name;
#Column(name = "date_from", columnDefinition = "timestamp with time zone not null")
private OffsetDateTime date_from;
}
The only value that varies is the date_from. I do not know, why new entries are being added to the database and not just get updated. I have the #EqualsAndHashcode that are being built based on primary Id key, so the date_from should not matter. Every method invocation creates a new entry with a completely new Id...

your problem is your
GenerationType.IDENTITY
the documentation says:
Indicates that the persistence provider must assign primary keys for
the entity using a database identity column.
Now the key question is, what SQL is getting generated. Can you please trace the insert SQLs generated?
Also I would prefer to use SEQUENCES of databases. So I do not have to mess around with the Identities of the persistence provider and any application will behave the same against the database if you use the SEQUENCES of databases for your ID/primary key columns.
Also a issue could be your DDL for the table creation, but I assume you know how to define the database tables with the given constraints.

Related

Why 'unique = true' is not working in hibernate entity?

I have created an entity with table name and column names.
I have also added the uniquekey constraint for a column name. But when I run, it shows the following error ;
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "alter table ingredient add constraint
UK_co7ro6kyijhfik027h0y4d3n3 unique (ingredient_name).
java.sql.SQLSyntaxErrorException: Specified key was too long; max key
length is 1000 bytes
After I run the spring boot application, I have tried to add the unique constraint manually in MySQL workbench. - DOES NOT WORK
I have added the below code - DOES NOT WORK
#Table(name = "ingredient", uniqueConstraints=#UniqueConstraint(name="uk_ingredient_name",columnNames="ingredient_name"))
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
Tried to create a table manually in Mysql workbench and tried to alter the column name with unique key later. THIS WORKS. But I want hibernate to do this for me.
#Entity
#Table(name = "ingredient")
public class Ingredient {
#Id
#Column(name="ingredient_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "ingredient_name" ,unique = true)
private String ingredientName;
I want to save the ingredients without any repetitions. I do not want duplicate entries.
I have gone through other answers and none of those solutions helped me.
I tried adding length = 20 in the #column.
It works completely fine without any error.
Could you remove
,unique = true
from #Column annotation and try, it seems there is an hibernate bug .When using unique true it does not obey the naming strategy.
For more information look at this post
#UniqueConstraint and #Column(unique = true) in hibernate annotation
and this one
https://hibernate.atlassian.net/browse/HHH-11586
After removing the unique=true I am able to generate the unique constraint with the specified name that is 'uk_ingredient_name'.Since it is already specified in the #Table annotation.
The error you are getting is because hibernate is generating a unique constraint name which is hitting the allowed limit and it is not taking into the account the constraint name you have declared.
#Column(name="username", length=8, unique=true)
worked fine for me.

How to generate auto incremented id for each table separately using SQL Server and Hibernate

I am trying to have separate auto incremented id generator for each of my entities.
The target database is a SQL Server database, and I am using Hibernate 5.2.4.Final. Also I am generating the tables from code.
I have an abstract BaseEntity and other child entities like below, and thus, I am aiming for TABLE_PER_CLASS.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {
protected long id;
#Id
#GeneratedValue(strategy = GenerationType.XXX)
#Column(name = "Id")
public long getId() {
return id;
}
}
#Entity
#Table(name = "Tags")
public class Tag extends BaseEntity {
}
Below are the different scenarios that I have faced so far:
setting XXX to AUTO: Creates a hibernate_sequence table in database, which I assume, will not provide separate id sequence for separate table.
setting XXX to SEQUENCE: Same as above. Referred this, while doing it.
setting XXX to TABLE: Creates a hibernate_sequences table, which can provide separate id sequence for separate table. However, I have found out that this is quite expensive (same reference as above), and also not my preferred strategy.
setting XXX to TABLE: Does not work for TABLE_PER_CLASS.
What I actually want to use is the native identity column of SQL Server. However, using the SEQUENCE is also an option, but I am not sure how to create and use one for each table from hibernate. Please suggest how either one of these two can be achieved.
Update on the answer by Khalil M. I tried it in 2 possible ways:
applying on BaseEntity -> does not create a separate sequence for each table, and rather creates a ID_SEQNCE, which queried before saving every new entity. So, I am not sure how this is any different than using GenerationType.TABLE.
applying it on each individual entity class -> while saving, the generator creates duplicate id.
for creating a sequence use this
#Id
#GeneratedValue(generator = "ID_SEQ", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "ID_SEQ", sequenceName = "ID_SEQNCE",allocationSize=1)
Edit:
You have to make it by yourself because what you are asking is not supported in Table per class
the id has to be shared across several tables. Consequently, when
using this strategy, you should not use AUTO nor IDENTITY.
for more info
Use strategy = GenerationType.IDENTITY
A short example is below
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
The GenerationType.IDENTITY is the easiest to use but not the best one from a performance point of view. It relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From a database point of view, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.

How to store entity with setted UUID?

I'm using MS SQL Server + Hibernate (JPA, more precisely, with EntityManager) and i faced with the problem: I need to store entity into appropriate table in my DB; this table has uniqueidentifier as primary key; and storing entity already has UUID (it's primary key), with witch it should be inserted into the DB.
Problem is that when i try to merge my entity, hibernate do some magic and store my entity with another UUID value. So, when I fetch this entity from db and take a look on it ID, I see inappropriate value.
So, I want to tell hibernate not to do that (or, maybe, there is another solution?).
My entity class:
public class Entity extends BaseEntity {
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2", strategy = "uuid2")
#Column(name = "id_column")
private UUID uuId;
// other fields, getters, setters
}
Also, I have one more 'annoyance': my IDE and my DB browser shows me another ID in that column. I mean, when I stop my app in the debug mode and look at the id of an entity, I see different value from a value in the database.
Thanks in advance!

Storing data using hibernate for inter related tables

I have two tables (say table A and table B). Table B has foreign key from table A primary key. I generated my java entities using netbeans IDE and i now have something like:
For table A:
#Entity
#Table(name = "WORKFLOW_TRANSACTION")
public class WorkflowTransaction implements {
#OneToMany(mappedBy = "wtId")
private Collection<WorkflowTask> workflowTaskCollection;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "APP_ID")
private BigDecimal appId;
.
.
.
For table B:
#Entity
#Table(name = "WORKFLOW_TASK")
public class WorkflowTask implements Serializable {
#JoinColumn(name = "WT_ID", referencedColumnName = "APP_ID")
#ManyToOne
private WorkflowTransaction wtId;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "TASK_ID")
private BigDecimal taskId;
#Column(name = "STEP_NUM")
private BigInteger stepNum;
.
.
.
Now my questions are:
What is the correct way to save data, should I create object for table B entity and set it in table A entity and then save table A?
I am generating entity beans using netbeans IDE feature. Are there any known disadvantages of it?, if yes, what?
You have bi-directional association, so you need to setTable B property in Table A entity class and also vice-versa. Since you have not declared cascading, you need to save the Table A entity first and then Table B entity.
Alternatively, if you save Table B and then Table A entity classes, the hibernate generates an extra SQL update command to maintain the relationship.
But if you want hibernate to save Table B entity when you save Table A entity then you need to add Cascade property:
#OneToMany(mappedBy = "wtId", cascade=CascadeType.ALL)
I don't think you will have any disadvantages if you use Netbeans for generating the entity classes, it save you time in writing the entities. But if you want to learn then writing entities without Netbeans is good.
To achieve this you can use two type of techniques XML mapping or Annotations
In both these techniques the common point is use
cascade="save-update"
What happens is that you set an attribute in one table getter and it will automatically insert into the many relation when inserting into one relation table

Using unique constraint on Hibernate JPA2

How can I implement my unique constraints on the hibernate POJO's? assuming the database doesn't contain any.
I have seen the unique attribute in #Column() annotation but I couldn't get it to work?
What if I want to apply this constraint to more than one column?
You can declare unique constraints using the #Table(uniqueConstraints = ...) annotation in your class
#Entity
#Table(uniqueConstraints=
#UniqueConstraint(columnNames = {"surname", "name"}))
public class SomeEntity {
...
}
Bascially, you cannot implement unique constraint without database support.
#UniqueConstraint and unique attribute of #Column are instructions for schema generation tool to generate the corresponsing constraints, they don't implement constraints itself.
You can do some kind of manual checking before inserting new entities, but in this case you should be aware of possible problems with concurrent transactions.
Therefore applying constraints in the database is the preferred choice.
In JPA2, you can add the Unique constraint directly to the field:
#Entity
#Table(name="PERSON_TABLE")
public class Person{
#Id
#Column(name = "UUID")
private String id;
#Column(name = "SOCIALSECURITY", unique=true)
private String socialSecurityNumber;
#Column(name = "LOGINID", unique=true)
private String loginId;
}
IMHO its much better to assign the unique constraint directly to the attributes than at the beggining of the table.
If you need to declare a composite unique key however, then declaring it in the #table annotation is your only option.

Categories

Resources