spring boot + hibernate table names queried in lower case - postgresql

I'm new to Spring boot and hibernate.
Below is my application prop file and the naming strategy implementation file.
When I try to push data to DB the below exception occurs ERROR: relation "nickname" does not exist.
I want access table name and column name always in uppercase.
Please help me to understand what went wrong.
NickName.java
#Entity
#Table(name="NICKNAME")
public class NickName {
application.properties
spring.datasource.url=jdbc:postgresql://192.168.239.129:5432/maindb
spring.datasource.username=pgdbuser
spring.datasource.password=pgdbuser
spring.jpa.generate-ddl=false
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL82Dialect
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
PhysicalNamingStrategyImpl.java
import java.io.Serializable;
import org.apache.commons.lang.StringUtils;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl implements Serializable{
public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();
#Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
String nameModified = StringUtils.upperCase(name.getText());
// Do whatever you want with the name modification
return new Identifier(nameModified, name.isQuoted());
}
#Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
String nameModified = StringUtils.upperCase(name.getText());
// Do whatever you want with the name modification
return new Identifier(nameModified, name.isQuoted());
}
}
Exception:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:242) ~[spring-orm-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) ~[spring-orm-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) ~[spring-orm-5.0.5.RELEASE.jar:5.0.5.RELEASE]
......
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
.......
Caused by: org.postgresql.util.PSQLException: ERROR: relation "nickname" does not exist
Position: 460
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178) ~[postgresql-42.2.2.jar:42.2.2]
Update 1: changed app.prop file as below
spring.datasource.url=jdbc:postgresql://192.168.239.129:5432/maindb
spring.datasource.username=pgdbuser
spring.datasource.password=pgdbuser
spring.jpa.generate-ddl=false
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect
spring.jpa.hibernate.naming.physical-strategy=com.theroot.rester.PhysicalNamingStrategyImpl
Note :
In my sql client just now checked
select * from "NICKNAME"; --Works
select * from NICKNAME; --doesn't Work

This should work :
1) Get rid of PhysicalNamingStrategyImpl.java
2) Make changes in application.properties as below :
spring.jpa.properties.hibernate.dialect =
org.hibernate.dialect.PostgreSQL95Dialect spring.jpa.hibernate.naming.implicit-
strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
3) In #Table add schema as well. ie., #Table(name="table", schema="schemaname")
This worked for me with Postgresql 10 with Hibernate 5.x and Spring Boot 2.1.x. If you are using an older version of Postgresql, then use appropriate PostgreSqlxxDialect from Spring.

Related

Spring Boot #Scheduled method can not access database relation

Jpa repositoy methods called from inside of a #Scheduled method is throwing PSQLException and saying the relation does not exist, where the same repository method is being executed fine without any problems from other parts of the code.
This is my #Configuration class for Scheduler,
#Configuration
#EnableScheduling
public class SchedulingConfig {
#Bean
public TaskScheduler taskScheduler() {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.setThreadFactory(new ThreadFactoryBuilder().setNameFormat("Scheduled-%d").build());
ConcurrentTaskScheduler taskScheduler = new ConcurrentTaskScheduler(executor);
taskScheduler.setTaskDecorator(new MasterTaskDecorator());
return taskScheduler;
}
}
And this is the #Scheduled annotated method,
#Scheduled(fixedRate = 60000, initialDelay = 60000)
public void scheduledRevalidationOfOpenJourney() {
List<JourneyEntity> openJourneys = journeyRepository.findAllByState(JourneyState.OPEN);
openJourneys.forEach(openJourney -> openJourney.getDatasets().forEach(validationService::removeRelatedViolation));
}
From there on, this is the exception being thrown,
2022-12-02 15:22:58.894 ERROR 32704 --- [ scheduling-1] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: relation "journey" does not exist
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
2022-12-02 15:23:58.896 ERROR 32704 --- [ scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: relation "journey" does not exist
As I mentioned before, the table 'journey' does already exist and its repository methods are already being executed without any problems elsewhere in the code. Can anybody please point out what is causing this scenario and what could be the solution to it?

Spring Boot ShedLock "relation "shedlock" does not exist"

I added ShedLock to my project to prevent working of scheduled job more than one time. I configured it like below but I'm getting
"org.postgresql.util.PSQLException: ERROR: relation "shedlock" does not exist" error.
This is lockProviderBean:
#Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(
JdbcTemplateLockProvider.Configuration.builder()
.withJdbcTemplate(new JdbcTemplate(dataSource))
.usingDbTime()
.build()
);
}
This is scheduled job:
#Scheduled(cron = "${cronProperty:0 00 23 * * *}")
#SchedulerLock(name = "schedulerLockName")
public void scheduledJob() {
..............
}
I added these notations to my class which contains schduledJob method:
#EnableScheduling
#Component
#Configuration
#EnableSchedulerLock(defaultLockAtMostFor = "2m")
I'm using Spring Data to do database operations and using these properties:
spring.datasource.url = jdbc:postgresql://ip:port/databaseName?currentSchema=schemeName
spring.datasource.driver-class-name = org.postgresql.Driver
spring.jpa.database = postgresql
spring.datasource.platform = postgresql
spring.datasource.hikari.maximum-pool-size=5
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.username = username
spring.datasource.password = password
You have to create the table as described in the documentation.
maybe this is what you are missing:
If you need to specify a schema, you can set it in the table name
using the usual dot notation new JdbcTemplateLockProvider(datasource,
"my_schema.shedlock")
I face this problem too even though shedlock table has been created.
Workarounds for this is by
Setting pg's user default schema using ALTER ROLE YourPgUser SET search_path TO ... , or
Specifing shedlock schema on LockProvider bean
#Bean
public LockProvider getLockProvider(#Autowired JdbcTemplate jdbcTemplate) {
jdbcTemplate.execute("SET search_path TO domaindbschema");
return new JdbcTemplateLockProvider(jdbcTemplate);
}
or another style
#Bean
public LockProvider getLockProvider(#Autowired JdbcTemplate jdbcTemplate) {
return new JdbcTemplateLockProvider(jdbcTemplate, "domaindbschema.shedlock");
}

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

Spring JPA #Param of filename for postgres COPY

I have the following interface which is connected to a PostgreSQL database:
public interface ExampleDAO extends JpaRepository<Example, Integer>
{
#Modifying
#Query(value="COPY my_table FROM :filename CSV HEADER", nativeQuery=true)
public int copyMyTable(#Param("filename") String filename);
}
But when I run it I get
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
I remove the #Param and hardcode the filename in and it works fine. The filename passed is:
copyMyTable("C:\\path\\to\\my\\file.csv");
I am totally at a loss on this one!
Judging from this thread Postgres doesn't support bind parameters in this kind of statement.

Spring data error

I have the following class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:my-ctx.xml"})
public class UserTests {
#Inject
private ApplicationContext applicationContext;
private UserRepository getUserRepository() {
return (UserRepository)applicationContext.getBean("userRepository", CrudRepository.class);
}
#Test
public void someTest() {
User user = new User();
user.setName("John Doe");
getUserRepository().save(user);
}
}
Running the test, I get the following error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException
...
root cause is
org.datanucleus.api.jpa.metamodel.SingularAttributeImpl.isVersion(SingularAttributeImpl.java:79)
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.findVersionAttribute(JpaMetamodelEntityInformation.java:92)
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:78)
org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:146)
org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:84)
org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:67)
...
where VersionMetaData vermd = mmd.getAbstractClassMetaData().getVersionMetaData(); is null.
Is this a bug?
I know that I can put something like #Inject UserRepository userRepository;, but taking into account how Spring Data works, these two should have the same result, right? And anyway the result will be the same error.
I'm using Spring data 1.4.1, DataNucleus 3.3.2, Spring 3.2.4.
Actually this is a DataNucleus bug and I filled in a bug report (with test and fix patch included): http://www.datanucleus.org/servlet/jira/browse/NUCJPA-250.
My workaround was to switch back to Spring Data 1.3.0.