JPA Using sequences as auto increment postgres - postgresql

I have this code:
#Entity
#Table(name = "table")
#SequenceGenerator(name="table_id_seq", sequenceName="table_id_seq", allocationSize=1)
public class TableExample extends BaseEntity implements Serializable {
/**
* The auto-generated primary key.
*/
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="table_id_seq")
#Column(name = "table_id")
private long id;
}
And I have this SEQUENCE in my database:
CREATE SEQUENCE table_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 2000
CACHE 1;
ALTER TABLE table_id_seq OWNER TO postgres;
When I am trying to persist a new object, I get this error:
org.apache.openjpa.persistence.PersistenceException: ERROR: current
transaction is aborted, commands ignored until end of transaction
block {prepstmnt 642363 SELECT NEXTVAL('table_id_seq')} [code=0,
state=25P02]
Am I missing something??
Thanks in advance

The error arose before that code; there's another problem earlier else that caused the transaction to be aborted. Examine your PostgreSQL server error logs or Hibernate/JPA logs to see where the FIRST error occurred, that'll be the real problem.

Related

Relation doesn't exist error with postgres 10.1 and hibernate

I have recently moved to postgres 10.1 database from oracle. I created all the tables manually via sql queries and made sure that I do not use any double quotes around table/column names.
CREATE TABLE MYSCHEMA.SOMETABLE (ID VARCHAR(20) NOT NULL primary key, DISPLAYTEXT VARCHAR(100)));// skipping other column names for brevity
Entity Class in code
#Entity
#Table(name = "MYSCHEMA", schema = "SOMETABLE")
public class SomeTable implements Serializable {
private static final long serialVersionUID = -4856666041227614340L;
#Column(name = "VERSION")
private String version;
#Column(name = "DISPLAYTEXT")
private String displayText;
//other columns
}
Using Jpa repository, I am querying this table.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "someEntityManagerFactoryContentDB",
transactionManagerRef = "sometransactionManagerContentDB",
basePackages = {"com.somepath.repository.content"})
public interface SomeSearchConfigRepository extends JpaRepository<SomeTable, String> {
List<SomeTable> findBySearchTypeAndActiveOrderBySequenceAsc(
String searchType, String active);
}
The issue is that it's not able to find this table and throws below error.
2019-06-24 09:56:26,781 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper:SQL Error: 0, SQLState: 42P01
2019-06-24 09:56:26,782 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper:ERROR: relation "MYSCHEMA.SOMETABLE" does not exist
Sql generated as per the logs
Hibernate:
/* select
generatedAlias0
from
SomeTable as generatedAlias0
where
(
generatedAlias0.searchType=:param0
)
and (
generatedAlias0.active=:param1
)
order by
generatedAlias0.sequence asc */ select
myalias_."ID" as ID1_3_,
myalias_."ACTIVE" as ACTIVE2_3_,
myalias_."COLUMNNAME" as COLUMNNA3_3_,
myalias_."DATATYPE" as DATATYPE4_3_,
myalias_."DISPLAYTEXT" as DISPLAYT5_3_,
myalias_."LENGTH" as LENGTH6_3_,
myalias_."LINKCOLUMN" as LINKCOLU7_3_,
myalias_."LINKSEARCH" as LINKSEAR8_3_,
myalias_."LOOKUPCOLUMN" as LOOKUPCO9_3_,
myalias_."LOOKUP_CATEGORY" as LOOKUP_10_3_,
myalias_."MULTISELECT" as MULTISE11_3_,
myalias_."REFERENCEKEY" as REFEREN12_3_,
myalias_."REFERENCETABLENAME" as REFEREN13_3_,
myalias_."REFERENCEVALUE" as REFEREN14_3_,
myalias_."SEARCHTYPE" as SEARCHT15_3_,
myalias_."SEQUENCE" as SEQUENC16_3_,
myalias_."TABLENAME" as TABLENA17_3_,
myalias_."VERSION" as VERSION18_3_
from
"MYSCHEMA"."SOMETABLE" myalias_
where
myalias_."SEARCHTYPE"=?
and myalias_."ACTIVE"=?
order by
myalias_."SEQUENCE" asc
Is it that somehow the annotations in entity classes causing this issue? What's going wrong here and how can I fix this issue with minimal changes in my code ?
I assume that you are using Spring Boot.
One option is to tell Hibernate to don't quote the names
spring.jpa.properties.hibernate.globally_quoted_identifiers=false
Or the other option is to create your tables also with quotes and go for all UPPERCASE names

Postgres insert record with Sequence generates error - org.postgresql.util.PSQLException: ERROR: relation "dual" does not exist

I am new to Postgres database.
I have a Java Entity class with the below column for ID:
#Entity
#Table(name = "THE_RULES")
public class TheRulesEntity {
/** The id. */
#Column(name = "TEST_NO", precision = 8)
#SequenceGenerator(name = "test_no_seq", sequenceName = "TEST_NO_SEQ")
#GeneratedValue(generator = "test_no_seq", strategy = GenerationType.AUTO)
#Id
private Long id;
/** The test val. */
#Column(name = "TEST_VAL", nullable = false, length = 3)
private String testVal;
Code:
rulesRepository.saveAndFlush(theRulesEntity)
Table:
CREATE TABLE THE_RULES
(
TEST_NO INT NOT NULL,
TEST_VAL VARCHAR(3) NOT NULL
)
CREATE SEQUENCE "TEST_NO_SEQ" START WITH 1000 INCREMENT BY 1;
When I try to insert a new record into the postgres database from my application (the ID value is null in Java code during Debug mode), then I get the below error:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "dual" does not exist
But If I insert the record manually into database table and then update the record from my application, then the record is updated successfully (Probably because the application uses the same ID value so no need to refer to the Sequence TEST_NO_SEQ value anymore)
Looks like the database is not able to access the sequence from dual table.
Could anyone help me how to fix this?
Thanks.
Thanks to Joop and a_horse_with_no_name, the issue is resolved
I have used Oracle driver which is wrong. I have updated my code to use Postgres driver
I created the Sequence again in the database with same name but without the Quotes
I used all capital-case letters in my Java entity class to refer to the sequence correctly

JPA Exception "lastval() not supported" in Greenplum

My code is running fine in Postgres, but when I switched to Greenplum, the following exception occurs:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: lastval() not supported
Error Code: 0
Call: select lastval()
Query: ValueReadQuery(name="SEQ_GEN_IDENTITY" sql="select lastval()")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1620)
...
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:874)
at org.eclipse.persistence.internal.jpa.QueryImpl.performPreQueryFlush(QueryImpl.java:967)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:207)
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:521)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400)
at module.AuthREST.login(AuthREST.java:103)
...
Caused by: org.postgresql.util.PSQLException: ERROR: lastval() not supported
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:302)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1009)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:644)
This is User model class:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id", nullable = false)
private Long id;
...
}
This is the code in AuthREST class:
...
#POST
#Path("login")
#Consumes({"application/x-www-form-urlencoded"})
public Response login(#Context HttpServletRequest request,
#Context HttpServletResponse response,
#FormParam("username") String username,
#FormParam("password") String password) {
request.login(username, password);
...
}
...
So how should i do avoid the exception in Greenplum?
The way sequences work in Greenplum:
the master has a "sequence server" running (if you look into the process list, you see a separate process)
every time a segment needs the next value from a sequence, it connects to the master and asks for the next value (this is overhead, by the way: http://engineering.pivotal.io/post/SERIAL_Datatype_Performance_in_Greenplum_Database/ )
The underlaying problem: the sequence server does not keep tab on the requests from the segment servers, therefore it does not know the last value (or values) per segment. Hence lastval() cannot be answered.
Even if the sequence server keeps a log of assigned sequence values: the way your query works, lastval() is executed on the master - but the master never actually inserted any data.
tl;dr: Retrieving the last value of a sequence in Greenplum is problematic. Even if lastval() is supported, the returned answer is likely not what you are looking for.
Reference your sequence table using sql last_value column. You can create your own last value function.
Example:
Select last_value from wcdl_dictionary.sq_dic_table_definition_table_id

JPA and Postgres sequence pre-allocation size setup incorrectly

I am not able to perist any Entity because of a problem with sequence. I use Glssfish 4, Postgres 9.3 + JPA + EJB3 and Netbeans 8.
Below the excpeption:
Finest: persist() operation called on: MyUser{id=null, email=a#e.it, password=test, firstname=test, lastname=test, company=Test}.
Finest: Execute query ValueReadQuery(sql="select nextval('mom_seq_id')")
Finest: Connection acquired from connection pool [read].
Finest: reconnecting to external connection pool
Fine: select nextval(mom_seq_id)
Finest: Connection released to connection pool [read].
Warning: Local Exception Stack:
Exception [EclipseLink-7027] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The sequence named [mom_seq_id] is setup incorrectly. Its increment does not match its pre-allocation size.
at org.eclipse.persistence.exceptions.ValidationException.sequenceSetupIncorrectly(ValidationException.java:1604)
at org.eclipse.persistence.sequencing.StandardSequence.createVector(StandardSequence.java:96)
...
The sequence on Postgres:
CREATE SEQUENCE my_seq_id
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 27
CACHE 1;
ALTER TABLE my_seq_id
OWNER TO postgres;
COMMENT ON SEQUENCE my_seq_id
IS 'Sequence for autoincrement id on MyClass';
And an extract of my Entity:
#Entity
#Table(name = "myuser")
#XmlRootElement
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="MYSEQ",
sequenceName="my_seq_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator="MYSEQ")
#Basic(optional = false)
#Column(name = "id")
private Integer id;
Can anyone explain what is wrong?
Thanks
I resolved my issue but I don't know why! I saw that the default value of allocationSize() is 50:
package javax.persistence;
#Target(value = {ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
#Retention(value = RetentionPolicy.RUNTIME)
public #interface SequenceGenerator {
public String name();
public String sequenceName() default "";
public String catalog() default "";
public String schema() default "";
public int initialValue() default 1;
public int allocationSize() default 50;
}
And I have updated my Postgres sequence increment_by value from 1 to 50 and now it works!
For reasons beyond my understanding, the JPA spec picked 50 as the default increment for a sequence generator.
PostgreSQL defaults to 1.
If the two don't match, things get ugly, because JPA thinks it can use values that someone else also thinks they have assigned. At least EclipseLink detects this; Hibernate just goes on merrily trying to re-use already assigned keys.
If your sequence is:
CREATE SEQUENCE my_seq_id
INCREMENT 1
then your mapping must reflect that:
#SequenceGenerator(name="MYSEQ",
sequenceName="my_seq_id", allocationSize=1)
I strongly suggest being explicit about the increment, even if you leave it at the default of 50 and alter the PostgreSQL sequence instead. It'll save your and others' sanity when debugging later.
Changing the value of INCREMENT from 1 to 50 into my Postgres sequence resolved the issue. As suggested by #unwichtich it is a good idea to specify allocationSize=50 attribute through the #SequenceGenerator annotation.

ORACLE AUTO INCREMENT jpa

i have prob with mapping sequence auto increment
#GeneratedValue(strategy=GenerationType.SEQUENCE)
i'm using on sql developer it work but when i try on netbeans i get the message
Caused by: java.lang.NullPointerException
Create a sequence named SOME_SEQ in your db for this particular table. And use the annotations above your id field. allocationSize=1 means increment the value by 1. And some_seq_gen_name is for unique labeling.
#Id
#Column(name = "id")
#GeneratedValue(generator="some_seq_gen_name")
#SequenceGenerator(name="some_seq_gen_name", sequenceName="SOME_SEQ", allocationSize=1)
private Long id;
UPDATE: Based on your comment, for commit try this one:
EntityTransaction et = em.getTransaction();
et.begin();
// write persist code here
et.commit();