In hibernate for columns annotated with #Column(unique = true) we get an exception when trying to insert a duplicate value for that column.
2022-07-31 19:47:18.112 ERROR 14372 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry ' someValue' for key 'business.UK_3h6o7iww8015m4q3yffbkqtrw'
So from the above log, I know that business is the table in which I am inputting a duplicate value.
Is there a way to know in which column the duplicate value is getting inserted into? Since a single table can have multiple unique columns.
In addition to what Davide D'Alto wrote, you can also enable SQL logging, e. g. as shown here.
You can check the SQL for the table creation:
show create table business;
or you can run the following query:
select COLUMN_NAME
from information_schema.KEY_COLUMN_USAGE
where TABLE_NAME = 'business' and CONSTRAINT_NAME='UK_3h6o7iww8015m4q3yffbkqtrw'
Related
I want to extract values from a CHECK constraint on a database table. The code is:
CONSTRAINT Shop_check_serviceType CHECK (service_type IN ('food or drink', 'entertainment', 'retail'))
In Postgres 12 there is a column named consrc in pg_catalog.pg_constraint. But I use Postgres 14 and I don't know how to extract the values there. I have tried to search the manual without success.
Use the dedicated function pg_get_constraintdef() to reverse-engineer the SQL-DDL code of constraint definition.
SELECT pg_get_constraintdef(oid)
FROM pg_catalog.pg_constraint
WHERE contype = 'c' -- CHECK constraint
AND conrelid = 'public.my_table'::regclass -- your table name here
AND connname = 'shop_check_servicetype'; -- lower-cased?
If you did not double-quote the constraint name "Shop_check_serviceType" it has been converted to lower-case.
Related:
Delete rows with foreign key in PostgreSQL
BTW, the (redundant) column consrc existed up to Postgres 11 and had already been dropped from pg_catalog.pg_constraint in Postgres 12. pg_get_constraintdef() reproduces what used to be in that column.
Quoting the release notes of Postgres 12:
Remove obsolete pg_constraint.consrc column (Peter Eisentraut)
This column has been deprecated for a long time, because it did not
update in response to other catalog changes (such as column
renamings). The recommended way to get a text version of a check
constraint's expression from pg_constraint is pg_get_expr(conbin, conrelid). pg_get_constraintdef() is also a useful alternative.
I have Stored bunch of insert statements in ArrayList.like below
List<String> script=new ArrayList<String>;
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (1, 'Madhava'));
script.add(INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (2, 'Rao'));
script.add(INSERT INTO PUBLIC.ADDRESS(ID, CITY) VALUES(1, 'Bangalore'))
script.add(INSERT INTO PUBLIC.ADDRESS(ID, CITY) VALUES(2, 'Hyd'));
I created connection to the postgresql using jdbc i get executed statments using for loop like below
try{
Connection con=DBConnections.getPostgresConnection();
Statment statment=con.createStatment();
for(String query:script){
executeUpdate(query);
}
}catch(Exception e){
e.printStackTrace();
}
If i get duplication key exception(i.e.Already record exist in postgresDB).
org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint "reports_uniqueness_index"
How to update the same statment(record) with update query into Postgres.
Is there any way to solve this ?
Is there any other better way to solve this?
Could you please explain...
Execute update sends a DML statement over to the database. Your database must already have a record which uses one of the primary keys either in the employees or address table.
You have to ensure you don't violate the primary key constraint. Violating the constraint is resulting in the exception.
Either change your query to an update statement, or delete the records which are causing conflict.
There is no way to get the key that caused the exception (though you can probably parse the error message, which is certainly not recommended).
Instead, you should try preventing this from ever happenning. There are at least 3 easy ways to accomplish this.
Make the database update the column
(in Postgresql you should use a serial type (which is basically an int data type)
CREATE TABLE employee
(
id serial NOT NULL,
--other columns here )
Your insert will now look like
script.add("INSERT INTO PUBLIC.EMPLOYEE(NAME) VALUES ('Madhava'));//no ID here
Create a sequence and have your JDBC code call the sequence' nexval method.
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (YOUR_SEQ_NAME.NEXTVAL(), 'Madhava'));
Create a unique ID in Java (least recommended)
script.add("INSERT INTO PUBLIC.EMPLOYEE(ID, NAME) VALUES (UUID.random(), 'Madhava'));//or Math.random() etc
I am trying to setup a query for my application to pull only values from a table that have a specific column set. Mostly this column will be null, but if you edit and save the item on the application end without putting anything in this field, then it saves a blank string to that database field.
I have tried the TSQL query:
SELECT * from TABLE where COLUMN is not NULL AND COLUMN != ''
This query returns the results I need, but when I run the same query in HQL:
SELECT OBJECT from TABLE where COLUMN is not NULL and COLUMN <> ''
Then it still contains the values that have a blank string in that column. I have tried this using HQL with the operators <> and !=, and have also tried converting it to a criteria object using Restrictions.ne("column","") but nothing seems to provide the result I need.
I tried Length as in the comments, but had no luck. With the length in the query hibernate generates the full query as so. the time_clock_id column is the one that i'm having the problem with. Hibernate is set to SQLServerDialect
select timezone0_.time_zone_id as time1_368_, timezone0_.version as version368_, timezone0_.modification_timestamp as modifica3_368_, timezone0_.time_offset as time4_368_, timezone0_.modification_user as modifica5_368_, timezone0_.name as name368_, timezone0_.description as descript7_368_, timezone0_.active as active368_, timezone0_.time_clock_id as time9_368_ from time_zone timezone0_ where timezone0_.active=1 and (timezone0_.time_clock_id is not null) and len(timezone0_.time_clock_id)>0
Rookie Mistake. There was another place within my action class where I was using a different query to build the select list in the application. This was resulting in the list being overwritten with all values instead of those that use blank. After snipping this duplication I can use the operator column <> '' and I am getting the correct results
In MySQL, if you specify ON DUPLICATE KEY UPDATE and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed. For example, if column a is declared as UNIQUE and contains the value 1, the following two statements have identical effect:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
I don't believe I've come across anything of the like in T-SQL. Does SQL Server offer anything comparable to MySQL's ON DUPLICATE KEY UPDATE?
I was surprised that none of the answers on this page contained an example of an actual query, so here you go:
A more complex example of inserting data and then handling duplicate
MERGE
INTO MyBigDB.dbo.METER_DATA WITH (HOLDLOCK) AS target
USING (SELECT
77748 AS rtu_id
,'12B096876' AS meter_id
,56112 AS meter_reading
,'20150602 00:20:11' AS time_local) AS source
(rtu_id, meter_id, meter_reading, time_local)
ON (target.rtu_id = source.rtu_id
AND target.time_local = source.time_local)
WHEN MATCHED
THEN UPDATE
SET meter_id = '12B096876'
,meter_reading = 56112
WHEN NOT MATCHED
THEN INSERT (rtu_id, meter_id, meter_reading, time_local)
VALUES (77748, '12B096876', 56112, '20150602 00:20:11');
There's no DUPLICATE KEY UPDATE equivalent, but MERGE and WHEN MATCHED might work for you
Inserting, Updating, and Deleting Data by Using MERGE
You can try the other way around. It does the same thing more or less.
UPDATE tablename
SET field1 = 'Test1',
field2 = 'Test2'
WHERE id = 1
IF ##ROWCOUNT = 0
INSERT INTO tablename
(id,
field1,
field2)
VALUES (1,
'Test1',
'Test2')
SQL Server 2008 has this feature, as part of TSQL.
See documentation on MERGE statement here - http://msdn.microsoft.com/en-us/library/bb510625.aspx
SQL server 2000 onwards has a concept of instead of triggers, which can accomplish the wanted functionality - although there will be a nasty trigger hiding behind the scenes.
Check the section "Insert or update?"
http://msdn.microsoft.com/en-us/library/aa224818(SQL.80).aspx
I am using Hibernate 4.1.0.Final with Spring 3
I have the following in Entity class
#Id
#Column(name = "PROJECT_NO")
#GeneratedValue(strategy=GenerationType.TABLE)
private String projectNumber;
Is it possible to use database trigger to populate the primary key of a table? Or I have to use a CustomGenerator for this?
When I tried the above I have the following exception
org.hibernate.id.IdentifierGenerationException: Unknown integral data type
for ids : java.lang.String
Database trigger doesn't have any sequence, it is using
SELECT NVL (MAX (project_no), 0) + 1 FROM projects
Edit 1
#GeneratedValue(generator="trig")
#GenericGenerator(name="trig", strategy="select",
parameters=#Parameter(name="key", value="projectNo"))
The above throws the following exception
Hibernate: select PROJECT_NO from PROJECTS where PROJECT_NO =?
java.lang.NullPointerException
exception in save null
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer.java:645)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValue(AbstractEntityPersister.java:4268)
at org.hibernate.id.SelectGenerator$SelectGeneratorDelegate.bindParameters(SelectGenerator.java:138)
at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:84)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2764)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3275)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
The problem is that you're using a String instead of a numeric value. Use a Long instead of a String, and your error will disappear.
AFAIK, you can't use a trigger to populate the ID. Indeed, Hibernate would have to retrieve the generated ID, but since it doesn't have an ID, I don't see how it could read back the row it has just inserted (chicken and egg problem).
You could use your SQL query to get an ID before inserting the row, but this strategy is inefficient, and has a risk of duplicate IDs in case of concurrent inserts. So I wouldn't use this strategy. You tagged your post with Oracle. I suggest you use a sequence. that's what they're for.
As of this on the Hibernate 3.3 documentation page you can do that.
select
retrieves a primary key, assigned by a database trigger, by selecting
the row by some unique key and retrieving the primary key value.