Postgres array in Hibernate entity - java

I am using postgres database and spring with hibernate in my project.
I just want to get some datas from DB, where the table having array datatype column in itself.
While I am getting from that table I am getting the following error.
ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: relation "reconcileprocess_bankstmtid" does not exist
Table structure as follows
CREATE TABLE reconcile_process
(
id bigserial NOT NULL,
comments character varying,
fk_last_modified_by bigint NOT NULL,
last_modified_date timestamp with time zone NOT NULL,
fk_remittance_transaction_fkey character varying,
fk_transaction_ref character varying,
process_type character varying,
reconcilled_date date,
fk_bank_stmt_id bigint[]
)
Entity class for that table
#Entity
#Table(name = "reconcile_process")
public class ReconcileProcess implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
Long id;
#Column(name = "comments")
String comments;
#Column(name = "fk_last_modified_by")
Long lastModifiedBy;
#Column(name = "last_modified_date")
Date lastModifiedDate;
#Column(name = "fk_transaction_ref")
String transactionRef;
#Column(name = "fk_remittance_transaction_fkey")
String remitTransactionRef;
#Column(name = "process_type")
String processType;
#Column(name = "reconcilled_date")
Date reconcilledDate;
#ElementCollection
#Column(name = "fk_bank_stmt_id")
List<Long> bankStmtId;

Hibernate does not support database arrays (java.sql.Array).
You get the error because Hibernate expects a separate table for List<Long> bankStmtId (because you didn't explicitly specify the table name, Hibernate assumes the default of <entity name>_<property name>, thus reconcileprocess_bankstmtid).
You can either switch to the supported approach with a separate table, or as explained here, you can try to write custom user type for database arrays.

Related

Logical delete and create with Hibernate

#Entity
#Table(name = "Country")
#SQLDelete(sql = "UPDATE Country SET date_deleted=NOW() WHERE code = ?")
#Where(clause = "date_deleted is NULL")
public class Country {
#Id
#Column(name = "code", nullable = false)
private String code;
#Column(name = "description")
private String description;
#Column(name = "date_deleted")
private Date date_deleted;
....
}
When I logic delete an Entity in the database with the code 'U1' and after, I created a new Entity with the same code 'Ü1', occurs an exception "duplicate entry". Has Hibernate an annotation to solve this problem?
edit:
The Error when I insert a new entity with the same code is this:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates
unique constraint "country_pkey" Detail: Key (code)=(AA) already
exists.
The table is:
CREATE TABLE public.country(
code bpchar(2) NOT NULL,
description bpchar(50) NULL,
date_deleted timestamp NULL,
CONSTRAINT country_pkey PRIMARY KEY (code),
CONSTRAINT constraint_country UNIQUE (date_deleted, code) -- I add this constraint
);
Since you manage the code column and you can have multiple entries with the same code, one solution would be to have an id column that is autogenerated.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
This will enable you to delete an object with the code 'U1' and add another one with the same code.
You can check this great tutorial: https://vladmihalcea.com/the-best-way-to-soft-delete-with-hibernate/

Implementing complex MAX function in Spring Boot/JPA query language

Spring Boot here using JPA/Hibernate and CrudRepository impls for managing persistence to my DB tables.
I have the following MySQL table:
CREATE TABLE IF NOT EXISTS price_scarcity_configs (
price_scarcity_config_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
price_scarcity_config_ref_id VARCHAR(36) NOT NULL,
price_scarcity_config_version BIGINT NOT NULL,
price_scarcity_config_updated_on DATETIME NOT NULL,
price_scarcity_config_fizz INTEGER NOT NULL,
CONSTRAINT pk_price_scarcity_configs PRIMARY KEY (price_scarcity_config_id),
CONSTRAINT uc_price_scarcity_configs_ref_id_and_version UNIQUE (price_scarcity_config_ref_id, price_scarcity_config_version)
);
These records will be versioned and different versions of the "same" record will all share the same price_scarcity_config_ref_id. Hence 2+ records can have the same price_scarcity_config_ref_id but will have two distinct different versions.
I'm also using the following JPA/Hibernate entity to model it:
// Uses Lombok annotations to generate getters/setters, etc.
#MappedSuperclass
#Data
#EqualsAndHashCode(callSuper=false)
public abstract class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String refId;
}
#Entity
#Table(name = "price_scarcity_configs")
#AttributeOverrides({
#AttributeOverride(name = "id", column = #Column(name = "price_scarcity_config_id")),
#AttributeOverride(name = "refId", column = #Column(name = "price_scarcity_config_ref_id"))
})
#Data
#EqualsAndHashCode(callSuper=false)
public class PriceScarcityConfiguration extends BaseEntity {
#Column(name = "price_scarcity_config_version")
private Long version;
#Column(name = "price_scarcity_config_updated_on")
private Date updatedOn;
#Column(name = "price_scarcity_config_fizz")
private Integer fizz;
}
I am now trying to write the PriceScarcityConfigurationRepository and need a fairly sophisticated query. Given a refId, I need to find the record who matches that ref id and has the highest/max version number. The raw SQL query to perform this is:
select
*
from
price_scarcity_configs pcs
inner join
(
SELECT
price_scarcity_config_ref_id,
MAX(price_scarcity_config_version) as max_ver
FROM
price_scarcity_configs
group by
price_scarcity_config_ref_id
) t
on
t.price_scarcity_config_ref_id = pcs.price_scarcity_config_ref_id
and
t.max_ver = pcs.price_scarcity_config_version;
Given my repository and using JPA/Hibernate's built-in query language/annos, how do I implement this query?
public interface PriceScarcityConfigurationRepository extends CrudRepository<PriceScarcityConfiguration,Long> {
#Query("FROM PriceScarcityConfiguration WHERE ??? HOW TO IMPLEMENT THE ABOVE QUERY HERE ???")
PriceSheetConfiguration fetchLatestVersionByRefId(#Param("refId") String refId);
}
You could use the following query instead and use setMaxResults(1)
FROM PriceScarcityConfiguration p WHERE p.refId = :refId ORDER BY p.version DESC
Or simply use the Spring Data notation
List<PriceSheetConfiguration> findFirstByRefIdOrderByVersionDesc(String refId);

Representing #EmbeddedId as SQL for H2 database

I am currently working on a Java project with Hibernate entities (more below). In order to test my data access object layers, I am using H2 database to populate an in-memory database and throwing queries at it. Until this point, everything is fine.
However, the problem comes when simulating the #EmbeddedId annotation.
#Entity
#Table(name = "BSCOBJ")
public class BasicObject extends AbstractDomainObject {
#EmbeddedId // This annotation here
private RestrainPK restrain;
#Embeddable
public static class RestrainPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "CODI", nullable = false)
private String coDi;
#Column(name = "COGA", nullable = false)
private String coGa;
#Column(name = "TYOR", nullable = false)
private String tyOr;
public RestrainPK() {
}
... // Getters and setters
}
}
"Simply" creating the table BSCOBJ and populating it gives no value when fetching data (of course, I checked that the request would give result "normally"). How do I represent this nested class in a SQL table creation / value insertion request ? Is that even possible ?
Thanks in advance,
EDIT
As requested, here is some samples about the SQL / Hibernate ran.
Creation request:
CREATE TABLE BSCOBJ (CODI VARCHAR(5) NOT NULL, COGA VARCHAR(5) NOT NULL, TYOR VARCHAR(5) NOT NULL);
Insertion request:
INSERT INTO BSCOBJ (CODI, COGA, TYOR) VALUES
('HELLO', 'MAT', 'REF'),
('BONJ', 'SOME', 'DAIL'),
('SOPA', 'KDA', 'RATIO');
Request given by Hibernate when trying to run the test code:
select r.restrain.tyOr from mypackage.BasicObject r where r.restrain.coDi = :coDi and r.restrain.coGa = :coGa
With the following values:
coDi = "BONJ";
coGa = "SOME";
Throws a NoResultException. I am expecting DAIL, from the second line of the INSERT request.
I have used #EmbeddedId only one time, but I think that you need #AttributeOverrides under your #EmbeddedId
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "idpk", column = #Column(name="IDPK", nullable = false),
#AttributeOverride(name = "code", column = #Column(name="CODE")
})
and remove your #Column annotations from FormulePK

Play Framework 2 Ebean specify default value for field

I have a simple model in Play Framework 2, and I would like to specify a default value to be inserted on a specify INT column if none is provided when the INSERT is performed.
Model:
#Entity
#Table(name = "DashboardOptions", schema = "dbo")
public class DashboardOptions extends Model implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
public Long id;
#Basic(optional = false)
#Column(name = "userId")
public Long userId;
#Column(name = "chartType")
public String chartType;
public String name;
public Integer size = 2;
I'd like to have the size column populate with 2 by default, however, if I specify the default value as above, my database evolution does not reflect this:
create table dbo.DashboardOptions (
id numeric(19) identity(1,1) not null,
userId numeric(19) not null,
chartType varchar(255),
name varchar(255),
size integer,
constraint pk_DashboardOptions primary key (id))
;
What I would expect to see is this:
create table dbo.DashboardOptions (
id numeric(19) identity(1,1) not null,
userId numeric(19) not null,
chartType varchar(255),
name varchar(255),
size integer default 2,
constraint pk_DashboardOptions primary key (id))
;
Use own columnDefinition like this:
#Column(columnDefinition = "integer default 2")
public Integer size = 2;
Another option is to use #PrePersist tag package javax.persistence. you can have a method decorated in your bean with #PrePersist and that method is called before Ebean.save call. so in this case the following code would set the default value of size to 2.
#PrePersist
protected void onCreate {
if (this.size == null)
this.size = 2;
}
This approach is applicable only within the context of ORM (Ebean) and obviously wouldn't work directly with SQL. The advantage of this method is that this is more database neutral in the sense that integer default 2 might not be a valid column definition string in some unknown strange RDBMS systems.

How to resolve hibernate table creation while its says unsuccessful creating table

I have a domain class name DataList
#Entity
#Table(name = "list_data")
public class ListData {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "sys_id")
private String sysId;
#Column(name = "name")
private String name;
#Column(name = "detail")
private String detail;
#Column(name = "values")
private String values;
//getters and setters
}
I have some others domain class..
I'm using hibernate 3.6 everything alright.
but somehow Im unsuccessful while creating this table.
2012-02-25 03:31:52,166 ERROR SchemaExport:274 Unsuccessful: create table list_data (id >integer not null auto_increment, detail varchar(255), name varchar(255), sys_id varchar(255), >values varchar(255), primary key (id))
2012-02-25 03:31:52,167 ERROR SchemaExport:275 You have an error in your SQL syntax; check the >manual that corresponds to your MySQL server version for the right syntax to use near 'values >varchar(255), primary key (id))' at line 1
I know my hibernate configuration is fine, I have some other domain class, they are working just fine.
I think that you cannot use values as a column name since it is a MySQL keyword (INSERT INTO ... VALUES() ).

Categories