Replace row when duplicate primarykey found - java

I have a table where I wish to replace a row when duplicate Primary (unique) key is found.
Create table History (
id varchar(5) not null,
name varcah(30),
primary key (id)
) engine=InnoDB character set utf8;
I'm using this with hibernate. id column is declared as #Id #Column(name="id", unique=true, nullable=false)
Help me change the above SQL, Hibernate annotations to allow REPLACE on duplicate primary key is found

The database Primary Key is not meant to be ever updated/replaced. There are workarounds but those are bad-practices.
You'd better use AUTO INCREMENT(MySQL), IDENTITY(MSSQL) or SEQUENCE(ORACLE, PostgreSQL) ID generation.
If you use MANUAL ID assignment and you get duplicate primary key violations, you have to check your current application concurrency design. Is the manual id assignment not thread-safe?
A database sequence or an AUTO-INCREMENT ID will save you from getting duplicate primary key violations.

Related

generate auto-incremented field in java spring data

I need to create a auto-incremented key (not a primary key) to use it as a file-name in spring-data
here what i tried:
#NotNull
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "BODY_FILE")
private long bodyFile;
in liquibase:
- column:
name: BODY_FILE
type: BIGINT
autoIncrement: true
but the field bodyfile is always 0.
#Generated value will ONLY work with a primary key.
It won't work with fields that are not a primary key.
It won't even work with the composite primary key.
But why not generated type can be applied for the non-primary field?
A possible answer is most of the older version of DB either does not support the AUTO_INCREMENT (Generated value) for the non-primary key field or If they support in a newer version that too has constraints- like for MySQL There can be only one AUTO_INCREMENT column per table, it must be indexed, and it cannot have a DEFAULT value.
So from where this zero comes from in your DB?
It is because of your datatype 'Long' its default value is getting stored in your DB.
For more details on #Generated value official documentation

Hibernate not persisting foreign keys in Mysql

I have an entity Property which has city field. Something like this:
#Entity
class Property {
...
#ManyToOne(fetch = FetchType.LAZY)
private City city;
...
}
So each property (e.g house or apartment) belongs to only one city.
Now here is a thing, if I try to log generated SQL by Hibernate, it is generating the foreign key in a right way:
Hibernate:
alter table property
add constraint FKdn1hnohufcwdr4a401xabcjn
foreign key (city_id_city)
references city (id_city)
However, if I check my Mysql database, there is no foreign key there, only index is generated:
show create table property;
leads to:
| property | CREATE TABLE `property` (
`id_property` int(11) NOT NULL AUTO_INCREMENT,
`created_at` datetime NOT NULL,
`deal_type` varchar(15) NOT NULL,
`publisher_type` varchar(15) NOT NULL,
`type` varchar(15) NOT NULL,
`updated_at` datetime NOT NULL,
`city_id_city` int(11) DEFAULT NULL,
PRIMARY KEY (`id_property`),
KEY `FKdn1hnohufcwdr4a401xabcjn` (`city_id_city`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
So the question is why there is no CONSTRAINT FOREIGN KEY () REFERENCES definition in my database?
The problem ended up to be the database engine after I switched to InnoDB engine it started working, as MyISAM does not implement foreign keys.
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
The annotation #ManyToOne is used to map two tables that have a relationship instance by a foreign key, it could not automatically create a foreign key in your database
You need to define the list Property in the City Entity and add the relationship there as well

Hibernate - Fetching entity having a composite primary key using any one of the primary key

I have an entity which has composite primary key. So i created primary class for the entity class with #EmbeddedId annotation.
I need help. While fetching that entity, is it possible to fetch the one of the primary key?
I tried to pass one of primary key to fetch that entity, other primary keys are set to zero and no result obtained.
Is there any way to fetch an entity (which has composite primary key) by specifying one of the primary key for that entity?
Sample code:
EmbeddedRiskDetailPK riskDetailPK = new EmbeddedRiskDetailPK ();
riskDetailPK.setRiskId(riskId);
Criteria criteria = hibernateDBSession.createCriteria(RiskDetail.class, "riskDetail")
.add(Restrictions.eq("riskDetail.embeddedRiskDetailPK ",riskDetailPK ));
isRecordCount = criteria.uniqueResult() != null ? ((Number)criteria.uniqueResult()).longValue() : 0;
1) You can have only one primary key for entity
2) If you compare by primary key, you compare by whole primary key, so you must give complete entity
3) If you specify ID by #IdClass annotation, you have fields on entity representing each component of primary key, and you can refer them in HQL or Criteria, so maybe you should consider redeign? I've made an example in that answer: Why is my EmbeddedId in hibernate not working?

JPA 2: Map Mapping fails for duplicate values

I'm trying to map a HashMap similar to the one that is specified as example 3 in the JavaDoc for #MapKeyJoinColumn (see http://www.objectdb.com/api/java/jpa/MapKeyJoinColumn):
#Entity
public class Student {
#Id int studentId;
...
#ManyToMany // students and courses are also many-many
#JoinTable(name="ENROLLMENTS",
joinColumns=#JoinColumn(name="STUDENT"),
inverseJoinColumns=#JoinColumn(name="SEMESTER"))
#MapKeyJoinColumn(name="COURSE")
Map<Course, Semester> enrollment;
...
}
The generated join table (generated with EclipseLink 2.3) has the following layout:
TABLE enrollments (
student_id bigint NOT NULL,
semester_id bigint NOT NULL,
course_id bigint,
CONSTRAINT enrollments_pkey PRIMARY KEY (student_id, semester_id)
)
Why is the primary key generated for Student and Semester and not for Student and Course? This doesn't make any sense in this case. With this primary key, a Student can participate in only one course per semester. 'student_id' and 'course_id' should be defined as primary key! This would also match the Java map definition (the key must be unique, but the same value may be assigned to different keys)
JPA sees the relationship as being between Student and Semester, as in a traditional #ManyToMany without the #MapKeyJoinColumn, and in traditional #ManyToMany duplicates would not be allowed, and the items are deleted by source/target ids, so the pk/index is desired to be on these.
For a finer level of control of the model, consider mapping the ENROLLMENTS table to an Enrollment Entity instead.
I can see from the Java model how you may desire different, so please log a bug/enhancement for this.

Hibernate #generatedvalue for HSQLDB

I have the following definition for an id field in an entity that is mapped to a table in HSQLDB.
...
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID")
private Integer id;
...
But this does not seem to generate the an unique id; instead an attempt is made to insert null into the column which results in failure. If, I manually create a sequence and generation strategy to use that sequence then the data is persisted as expected.
Doesn't a generation strategy of auto imply that the provider (hibernate in this case) will automatically choose the correct approach and do all the heavy lifting as needed (create sequence, use a native approach or whatever works for that particular platform)? Is my understanding incorrect?
Doesn't a generation strategy of auto imply that the provider (hibernate in this case) will automatically choose the correct approach and do all the heavy lifting as needed (create sequence, use a native approach or whatever works for that particular platform)? Is my understanding incorrect?
It does in theory (it defaults to IDENTITY with HSQLDB) and it works for me. This begs the following questions:
What dialect are you using (just in case)?
How did you create the table?
Can you show the DDL (activate the logging of org.hibernate.tool.hbm2ddl if required)?
How do you insert (through Hibernate's API, right?)?
Here is a sample DDL for an entity Foo when using HSQLDB:
create table Foo (
id bigint generated by default as identity (start with 1),
bar varchar(100),
primary key (id)
)
I created the table using the HSQL DB manager. Just normal create table address... I had not set the id column as identity in my case - just set it as primary key.
Then you have your answer, use an IDENTITY column.
While Hibernate does choose the right strategy and does generate the appropriate INSERT statements (passing null into the id which is expected to be persisted into an IDENTITY column), it won't create or alter your physical model if you don't use the DDL generation and export capabilities.
I had the same issue when using a JpaSchemaGenerator utility class that I wrote.
When generating the schema for a org.hibernate.dialect.HSQLDialect (where I use a SEQUENCE to generate my unique IDs), I use the following Hibernate property:
hibernate.id.new_generator_mappings=true
This results in the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID NUMBER(19,0) NOT NULL,
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR2(255 CHAR),
BAT_MAT_ID NUMBER(19,0),
PRIMARY KEY (BAT_ID)
);
But when I use this same property in my utility class to generate a schema using the org.hibernate.dialect.HSQLDialect, I get the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID BIGINT NOT NULL,
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR(255),
BAT_MAT_ID BIGINT,
PRIMARY KEY (BAT_ID)
);
This would mean that if I created a Batch without an ID, it would not generate it for me and the NOT NULL constraint would cause an exception.
If I change the Hibernate property to the following:
hibernate.id.new_generator_mappings=false
Then it would generate the following CREATE statement:
CREATE TABLE BATCH (
BAT_ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
BAT_EXPIRY_DATE TIMESTAMP,
BAT_NUMBER VARCHAR(255),
BAT_MAT_ID BIGINT,
PRIMARY KEY (BAT_ID)
);
Which works perfectly when creating JPA entities with Hibernate.

Categories