Relation doesn't exist error with postgres 10.1 and hibernate - postgresql

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

Related

#Audited table and byte[] #Lob field problem

I have adudited table with #Lob field. Without #Audited saving object by Spring CrudRepository works ok, but when i want audit turn on i get error: PSQLException: ERROR: column "content" is of type oid but expression is of type bytea. How to resolve this ? Content column in PostgreSQL database is oid type (for both tables). On Hibernate 5.x the same configuration works, but not o Hibernate 6.x.
#Entity
#Audited
#Table(name = "up_test")
#Getter #Setter
public class UploadTestEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "up_test_seq")
#TableGenerator(table = "id_generator", name = "up_test_seq", initialValue = 1, allocationSize = 1)
private Integer id;
#Lob
private byte[] content;
}
Just remove the #Lob annotation.
The Postgres JDBC driver does not support handling the bytea type via the JDBC LOB APIs setBlob()/getBlob(). I don't know why, and it seems like something that should be supported.
But on the other hand, you don't need it here. The most natural way to handle a field of type byte[] mapping to bytea is to use setBytes()/getBytes(), which is the job of Hibernate's VarbinaryJdbcType.
I don't know where people got the idea that they needed to use #Lob for this instead of just going with the default mapping for byte[].

Is there a way to generate liquibase changelog from jpa entities with hibernate TypeDef?

I am using jpa-buddy to generate liquibase changelog (sql format) from jpa (hibernate) entities.
I am using hibernate-types-55 to map java Enum to posgres Enum. I do this as follow:
#Entity
#TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
public class MyEntity {
#Enumerated(EnumType.STRING)
#Type(type = "pgsql_enum")
private MyEnumType myEnum;
}
The generated DDL with jpa-buddy is:
CREATE TABLE my_entity
(
my_enum VARCHAR(255),
);
when remove
#Enumerated(EnumType.STRING)
I get
CREATE TABLE my_entity
(
my_enum UNKNOWN__COM.VLADMIHALCEA.HIBERNATE.TYPE.BASIC.POSTGRESQLENUMTYPE,
)
The problem is I can't generate postgres enum type from entity.
what I am expecting is a generated DDL like:
create type my_enum_type as enum ('ENUM1', 'ENUM2', 'ENUM3');
CREATE TABLE my_entity (
my_enum my_enum_type,
);
Has anyone managed to do this in the past ?
Thank you
I found the issue same with your issue:
Java Enums, JPA and Postgres enums - How do I make them work together?
You must create MyEnumConverter.class after imoprt Hibernate-core.jar.
In your case, try:
#TypeDef(name="myEnumConverter", typeClass=MyEnumConverter.class)
public #Entity class MyEntity {
public static enum Mood {ENUM1, ENUM2, ENUM3}
#Type(type="myEnumConverter") MyEnumType myEnum;
}
But I think, using JPA entity isn't good for create table.
You should create table, view, etc,... by SQL native after that you create table if run success SQL statement.

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 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.

Mapping Java enum on Postgres enum with EclipseLink

I am making first attempts with JPA (EclipseLink implementation) and feel quite stuck:
In PostgreSQL I have the following db schema
CREATE TYPE mood AS ENUM ( 'sad', 'happy', 'enthusiastic' );
CREATE TABLE person (
pk BIGINT PRIMARY KEY,
name VARCHAR NOT NULL,
mood mood NOT NULL
);
CREATE SEQUENCE person_pk_seq INCREMENT BY 100 MINVALUE 100;
Which works pretty fine, as this insert shows INSERT INTO PERSON (PK, mood, name) VALUES (3, 'happy', 'Joe') (Committing the pk as String makes no difference.)
On the JPA side I wrote the following class:
package testdb;
import java.io.Serializable;
import javax.persistence.*;
import org.eclipse.persistence.annotations.*;
#Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
public enum Mood {
sad, happy, enthusiastic;
}
#Id
#SequenceGenerator(
name="PERSON_PK_GENERATOR",
sequenceName="PERSON_PK_SEQ",
allocationSize = 100
)
#GeneratedValue(
strategy=GenerationType.SEQUENCE,
generator="PERSON_PK_GENERATOR"
)
public Long pk;
#Enumerated( EnumType.STRING )
#Column( name = "mood" )
#ObjectTypeConverter( name = "moodConverter", objectType = Mood.class,
dataType = String.class, conversionValues = {
#ConversionValue( objectValue = "sad", dataValue = "sad" ),
#ConversionValue( objectValue = "happy", dataValue = "happy" ),
#ConversionValue( objectValue = "enthusiastic", dataValue = "enthusiastic" )
})
#Convert( "moodConverter" )
public Mood mood;
#Column( name = "name" )
public String name;
public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("TestDb.jpa.tests" );
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
Person p = new Person();
em.persist( p );
System.out.println(p.pk);
p.name = "Joe";
p.mood = Mood.enthusiastic;
em.getTransaction().commit();
Query q = em.createQuery( "select p from Person p" );
Person x = (Person)q.getResultList().get(0);
System.out.println( x.pk + " :: " +x.mood );
em.close();
}
}
However, this example is not working and I have no clue what the problem is:
[EL Warning]: 2012-06-05 15:28:20.646--UnitOfWork(845463623)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.BatchUpdateException: Batch-Eintrag 0 INSERT INTO PERSON (PK, mood, name) VALUES ('801', 'enthusiastic', 'Joe') wurde abgebrochen. Rufen Sie 'getNextException' auf, um die Ursache zu erfahren.
Error Code: 0
Call: INSERT INTO PERSON (PK, mood, name) VALUES (?, ?, ?)
bind => [3 parameters bound]
When I alter the column type of table person to varchar and remove the annotations #Convert and #ObjectTypeConverter everything is working as expected, as well.
Any ideas?
Why do you use a #ObjectTypeConverter, you can map Enumerations out of the box with eclipse link as shown here. #Enumerated is part of JSR-220 whereas #ObjectTypeConverter is a proprietary extension from EclipseLink JPA Extensions.
#Enumerated(EnumType.STRING)
#Column(name = "mood")
private Mood mood;
Try removing the #Enumerated( EnumType.STRING ) as it might be overriding the converter settings.
What is the mood type? This is not a standard JDBC type, so this is the reason for your error.
How does Postgres require this type to be bound through JDBC? It seems odd it does not auto convert varchar values.
I did a little looking, and it seems to return this type as PGObject, so you will need to own custom Converter that converts between your Java enum, and a Postgres enum. You will also need to set the jdbcType on the DatabaseField in your converters init method to OTHER.
Please log a bug on EclipseLink to have support added to the Postgres platform for this type.
I think disabling parameter binding would also work.
I'm 10 years late but...
Adding stringtype=unspecified to the connection string will do the trick.
I use connection strings like:
jdbc:postgresql://localhost:5432/mydatabase?stringtype=unspecified
And then, all fields annotated with #Enumerated(STRING) are automatically converted to the pg enum type.