Spring Data JPA throwing No Results were returned for custom Insert Statement - postgresql

I have a table say it Name(name,lock,timestamp). name column is Primary key and for inserting i am not using inbuilt save method with does insert/update. My Requirement is to just insert and not to update if there exist. so I wrote my custom query for inserting data. When i run the query it inserts data into table but throws exception saying Caused by: com.edb.util.PSQLException: No results were returned by the query.
I tried using my custom insert with with constraint on confict.
#Repository
public interface MyNameRepository extends JpaRepository<MyEntity, Long> {
#Query(value="INSERT into name(name,lock,updtedTime) values (?,?,?) on conflict ON CONSTRAINT unique_name do nothing",nativeQuery = true)
public void insertData(String name,int lock,Timestamp startTime);
}
I expect it should insert without any error.

Related

How to retrieve generated fields such as generated id or updated_at field by a trigger during insert/update in springboot

In postgres it's possible to retrieve computed values using returning. I have a generated id field and a field called updated_at that is updated by a trigger whenever a row is modified.
I'd like to achieve something like this but looks like it's not working. Not sure it's the right syntax for bulk insert.
#Query(value = "INSERT INTO entities VALUES :values RETURNING *",nativeQuery = true)
List<Entity> insertAndReturn(#Param("values") List<Entity> entities);
The error is:
java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing
I have also looked into jdbctemplate but it seems we are losing the benefit of entity mapping and we need to write own customized mapper.
That's not going to work. Native SQL doesn't support multi-valued parameters. You have to list all parameters individually. You can try something like this
default List<Entity> insertAndReturn(#Param("values") List<Entity> entities) {
for (int i = 0; i < entities.size(); i++ ) {
entities.set(i, insertAndReturn(entities.get(i)));
}
return entities;
}
default Entity insertAndReturn(Entity entity) {
return insertAndReturn(entity.getColumn1(), entity.getColumn2());
}
#Query(value = "INSERT INTO entities_table(column1, column2) VALUES (:column1, :column2) RETURNING *",nativeQuery = true)
Entity insertAndReturn(#Param("column1") String column1, #Param("column2") String column2);

Numeric types mapping issue in Spring Data R2dbc with postgres

I tried to use Spring Data R2dbc/Postgres in a sample application.
Spring Boot 2.4.0-M2
R2dbc Postgres (managed by Spring Boot)
Spring Data R2dbc 1.2.0-M2(managed by Spring Boot)
The table scripts.
CREATE SEQUENCE IF NOT EXISTS ORDERS_ID_SEQ;
CREATE TABLE IF NOT EXISTS ORDERS(
ID INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('ORDERS_ID_SEQ') ,
CUST_ID BIGINT NOT NULL,
AMOUNT REAL NOT NULL
);
ALTER SEQUENCE ORDERS_ID_SEQ OWNED BY ORDERS.ID;
The data.sql:
-- INSERT SAMPLE DATA
DELETE FROM ORDERS;
INSERT INTO ORDERS(CUST_ID, AMOUNT) VALUES (1, 100.2);
I use a ResourceDatabasePopulator to populate the data, it works.
But when I was trying to save the data by Repository, failed.
#Table(value = "ORDERS")
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class Order implements Serializable {
#Id
#Column(value = "ID")
private Integer id;
#Column(value = "CUST_ID")
private Long customerId;
// use BigDecimal or Java Money API in the real-world application.
#Column(value = "AMOUNT")
private Double amount;
}
public interface OrderRepository extends R2dbcRepository<Order,Integer> {
}
// in application runner.
orders .save(Order.builder().customerId(c.getId()).amount(201.0).build())
It threw an exception like this:
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.UnsupportedOperationException: Binding parameters is not supported for the statement 'INSERT INTO ORDERS (CUST_ID, AMOUNT) VALUES (?, ?)'
Caused by: java.lang.UnsupportedOperationException: Binding parameters is not supported for the statement 'INSERT INTO ORDERS (CUST_ID, AMOUNT) VALUES (?, ?)'
at io.r2dbc.postgresql.SimpleQueryPostgresqlStatement.bind(SimpleQueryPostgresqlStatement.java:78) ~[r2dbc-postgresql-0.8.4.RELEASE.jar:0.8.4.RELEASE]
at io.r2dbc.postgresql.SimpleQueryPostgresqlStatement.bind(SimpleQueryPostgresqlStatement.java:44) ~[r2dbc-postgresql-0.8.4.RELEASE.jar:0.8.4.RELEASE]
The complete codes is here.
Updated: Give up extending from AbstractR2dbcConfiguration, and get resovled when following the official guide.

Getting Exception while inserting data in Redshift DB

while fetching data from database It is working fine when trying to insert data in Redshift database getting exception
MY POJO class : Quote.java
#Entity
public class Quote {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Integer id;
#Column(name="user_name")
private String username;
private String quote;
}
Getting Exception :
com.amazon.support.exceptions.ErrorException: [Amazon](500310) Invalid operation: relation "hibernate_sequence" does not exist;
We cannto create sequence in Redshift but we can create sequence in postgresql
and when I am connect with redshift + spring-data-jpa then it is using postgresql db
hbm2ddl.auto = update
I have tried with identity also
I did GenerationType.TABLE and created table called sequence to overcome this.
CREATE TABLE sequence(seq_count bigint, seq_name varchar(65535));
But it seems to be very slow.

How can I update a row which EclipseLink uses for #TableGenerator or insert a new row into that table?

I want to integrate a JDBC based application into an Java EE application running in GlassFish which uses EclipseLink JPA 2.5 with MariaDB (a MySQL clone).
The JDBC based application imports data from flat files into some database tables and requires to update the next serial value for the primary keys by executing:
UPDATE dbtable SET nextid = 4711 WHERE name = 'table4Import';
using a standard JDBC connection. This statement throws an SQL timeout exception because the row is locked. It seems to be locked by EclipseLink which uses the same table for its table generator. Here is (parts of) the table containing the serial values:
CREATE TABLE dbtable (
dbtid bigint not null primary key,
dbtname varchar ( 50 ) not null,
dbtnextid bigint );
This is the code for one of the JPA entities:
#Entity
#Access(AccessType.PROPERTY)
#Table( name = "table4Import" )
public class Table4ImportClass {
private Long id = null;
#NotNull
#Id
#TableGenerator( name="table4Import", allocationSize=1,
table="dbtable", pkColumnName="dbtname",
pkColumnValue="table4Import", valueColumnName="nextid" )
#GeneratedValue( generator="table4Import", strategy=GenerationType.TABLE )
public Long getId() { return this.id; }
...
Addendum: It is not even possible to insert a new row into that table. EclipseLink seems to lock the complete table. It is still possible to modify the table (insert & update) from another program. The lock scope seems to be the JVM in which EclipseLink is running.
Addendum 2: Put this as a bug into EclipseLink bug tracker 455756

JPA Error : The entity has no primary key attribute defined

I am using JPA in my application. In one of the table, I have not used primary key (I know its a bad design).
Now the generated entity is as mentioned below :
#Entity
#Table(name="INTI_SCHEME_TOKEN")
public class IntiSchemeToken implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="CREATED_BY")
private String createdBy;
#Temporal( TemporalType.DATE)
#Column(name="CREATED_ON")
private Date createdOn;
#Column(name="SCH_ID")
private BigDecimal schId;
#Column(name="TOKEN_ID")
private BigDecimal tokenId;
public IntiSchemeToken() {
}
public String getCreatedBy() {
return this.createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getCreatedOn() {
return this.createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
public BigDecimal getSchId() {
return this.schId;
}
public void setSchId(BigDecimal schId) {
this.schId = schId;
}
public BigDecimal getTokenId() {
return this.tokenId;
}
public void setTokenId(BigDecimal tokenId) {
this.tokenId = tokenId;
}
}
Here In my project, eclipse IDE shows ERROR mark(RED colored cross) on this class and the error is "The entity has no primary key attribute defined".
Can anyone tell me, How to create an entity without primary key ?
Thanks.
You can't. An entity MUST have a unique, immutable ID. It doesn't have to be defined as a primary key in the database, but the field or set of fields must uniquely identify the row, and its value may not change.
So, if one field in your entity, or one set of fields in your entity, satisfies these criteria, make it (or them) the ID of the entity. For example, if there is no way that a user can create two instances in the same day, you could make [createdOn, createdBy] the ID of the entity.
Of course this is a bad solution, and you should really change your schema and add an autogenerated, single-column ID in the entity.
If your Primary Key(PK) is a managed super class which is inherited in an entity class then you will have to include the mapped super class name in the persistence.xml file.
Look at the bug report:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=361042
If you need to define a class without primary key, then you should mark that class as an Embeddable class. Otherwise you should give the primary key for all entities you are defining.
You can turn off (change) validation that was added.
Go to workspace preferences 'Java Persistence->JPA->Errors/Warnings' next 'Type' and change 'Entity has no primary key' to 'Warnning'.
In addition to http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#No_Primary_Key you can use some build-in columns like ROWID in Oracle:
Oracle legacy table without good PK: How to Hibernate?
but with care:
http://www.orafaq.com/wiki/ROWID
Entity frameworks doesn't work for all kind of data (like statistical data which was used for analysis not for querying).
Another solution without Hibernate
If
- you don't have PK on the table
- there is a logical combination of columns that could be PK (not necessary if you can use some kind of rowid)
-- but some of the columns are NULLable so you really can't create PK because of DB limitation
- and you can't modify the table structure (would break insert/select statements with no explicitly listed columns at legacy code)
then you can try the following trick
- create view at database with virtual column that has value of concatenated logical key columns ('A='||a||'B='||'C='c..) or rowid
- create your JPA entity class by this view
- mark the virtual column with #Id annotation
That's it. Update/delete data operations are also possible (not insert) but I wouldn't use them if the virtual key column is not made of rowid (to avoid full scan searches by the DB table)
P.S. The same idea is partly described at the linked question.
You need to create primary key ,If not found any eligible field then create auto increment Id.
CREATE TABLE fin_home_loan (
ID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (ID));
Just add fake id field.
In Postgres:
#Id
#Column(name="ctid")
String id;
In Oracle:
#Id
#Column(name="ROWID")
String rowid;