java


Initialize a database with a script using Spring JDBC fails


I am trying to initialize my database with a view and a rule following 75.3 Initialize a database using Spring JDBC.
75.3 Initialize a database using Spring JDBC
Spring JDBC has a DataSource initializer feature. Spring Boot enables it by default and loads SQL from the standard locations schema.sql and data.sql (in the root of the classpath). In addition Spring Boot will load the schema-${platform}.sql and data-${platform}.sql files (if present), where platform is the value of spring.datasource.platform, e.g. you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql, postgresql etc.). Spring Boot enables the fail-fast feature of the Spring JDBC initializer by default, so if the scripts cause exceptions the application will fail to start. The script locations can be changed by setting spring.datasource.schema and spring.datasource.data, and neither location will be processed if spring.datasource.initialize=false.
This section says that if I put a schema-postgresql.sql it should initialize my database with the script that the file contains.
Unfortunately the script ends with the following error
Caused by: org.postgresql.util.PSQLException: syntax error at end of input SQL state
Position: 169
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2310) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2023) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:217) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:421) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:318) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:310) ~[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7]
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:473) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 64 common frames omitted
However if I run this script from pgAdminIII there are no errors and the view with the corresponding rule are created without any problem.
What am I doing wrong here?
This is the structure of my Spring Boot example to reproduce it.
src/main/java/com/example/model/Person.java
package com.example.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1334414548362400146L;
#Id
private long id;
#Column(nullable = false, length = 100)
private String name = "";
#Column(nullable = false, length = 100)
private String surname = "";
}
src/main/java/com/example/model/PersonRole.java
package com.example.model;
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
#Entity
public class PersonRole implements Serializable {
private static final long serialVersionUID = -3953147119216643027L;
#EmbeddedId
private PersonRoleKey primaryKey;
}
src/main/java/com/example/model/PersonRoleKey.java
package com.example.model;
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ForeignKey;
import javax.persistence.ManyToOne;
import javax.persistence.PrimaryKeyJoinColumn;
#Embeddable
public class PersonRoleKey implements Serializable {
private static final long serialVersionUID = 2105526364632711640L;
#ManyToOne(optional = false)
#PrimaryKeyJoinColumn(foreignKey = #ForeignKey(name = "person_fk"))
private Person person;
#Enumerated(EnumType.STRING)
private Role role;
}
src/main/java/com/example/model/Role.java
package com.example.model;
public enum Role {
ADMIN, USER;
}
src/main/java/com/example/DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
src/main/resources/application.properties
#Database configuration
spring.datasource.url: jdbc:postgresql://localhost:5432/postgres
spring.datasource.driverClassName: org.postgresql.Driver
spring.datasource.username: postgres
spring.datasource.password: postgres
spring.datasource.platform: postgresql
spring.datasource.continue-on-error: false
spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql: true
spring.jpa.generate-ddl: true
spring.jpa.hibernate.ddl-auto: update
#default means org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
spring.jpa.properties.hibernate.implicit_naming_strategy: default
spring.jpa.hibernate.naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#spring.jpa.properties.hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
spring.jpa.properties.hibernate.auto_quote_keyword: true
spring.jpa.show-sql: false
src/main/resources/schema-postgresql.sql
CREATE OR REPLACE VIEW v_peoples_roles AS
SELECT p.id,
p.name,
p.surname,
pr.role
FROM (person p
JOIN personrole pr ON ((p.id = pr.person_id)));
CREATE OR REPLACE RULE insert_v_peoples_roles AS
ON INSERT TO v_peoples_roles DO INSTEAD ( INSERT INTO person (id, name, surname)
VALUES (new.id, new.name, new.surname);
INSERT INTO personrole (person_id, role)
VALUES (new.id, new.role);
);
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<hibernate.version>5.2.2.Final</hibernate.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The whole code could be downloaded from here.
EDIT
Based on the poz's comment I changed the schema-postgresql.sql to
CREATE OR REPLACE VIEW v_peoples_roles AS
SELECT p.id,
p.name,
p.surname,
pr.role
FROM (person p
JOIN personrole pr ON ((p.id = pr.person_id)));
CREATE OR REPLACE FUNCTION insert_into_v_people_roles() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO person (id, name, surname) VALUES (new.id, new.name, new.surname);
INSERT INTO personrole (person_id, role) VALUES (new.id, new.role);
RETURN new;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS insert_v_peoples_roles ON v_peoples_roles;
CREATE TRIGGER insert_v_peoples_roles INSTEAD OF INSERT ON v_peoples_roles FOR EACH ROW EXECUTE PROCEDURE insert_into_v_people_roles();
But it produces another error, exactly like predicted.
ERROR: unterminated quoted string at or near "$$ BEGIN INSERT INTO person (id, name, surname) VALUES (new.id, new.name, new.surname)"
Because pozs has not posted his own answer and some time has passed I am doing it by myself.
Changing the CREATE RULE to an INSTEAD OF triggered and $$-quoting to '-quoting solved the problem. The only issue was that I had to escape all the apostrophes inside function definitions. Was not that big of a pain though.

Related Links

Change parts of a string
Some javafx classes cannot be resolved in Eclipse using Java SE 8u25
How to deserialize this json
pass jsp parameter to another using button
OpenGL ES 1.0 strange texture behavior
How to add text as a header or footer?
why setting an adapter to a listView doesn't show the list content?
How do I make a variable equal the system time and now keep changing to the system time
Can't put Double number in BigDecimal variable
Java safest way to check client jar server side
Deploy WAR on Tomcat
UnsupportedClassVersionError while using Jmockit in a Java 1.5 Project
adding item to jlist from jlist
Constructor with many required parameters
Unity 2d instantiating on mouse location trouble, Please advise
String replace according to position?

Categories

HOME
compiler-construction
variables
activiti
minimum-spanning-tree
deezer
homebrew
layout
mean-stack
read-eval-print-loop
razor
gorm
maude-system
metatrader4
node-pdfkit
here-api
php-7.1
ups
vaadin7
systemc
propel
interop
oxyplot
custom-wordpress-pages
swiftlint
reverse-proxy
scriptcs
bootstrap-material-design
linkerd
buck
nat
fabric8
iframe-resizer
http-status-code-503
titanium-mobile
caret
overriding
restlet
disassembling
x11-forwarding
dynamics-crm-2013
elasticsearch-plugin
spring-security-kerberos
keydown
heightmap
galleria
fault
dotcover
filepicker
upstart
komodoedit
jedis
python-c-api
winscp-net
setter
lift-json
gcsfuse
firmata
color-picker
adxstudio-portals
player
flash-cs5
hover-over
ptrace
photobucket
pervasive-sql
marching-cubes
wordml
tarjans-algorithm
twirl
gui-test-framework
client-side-templating
phpthumb
message-driven-bean
monomac
intentservice
page-layout
oam
jquery-mobile-dialog
specification-pattern
isnullorempty
ticoredatasync
windows-phone-7.1.1
coredump
xdomainrequest
calling-convention
propagation
locate
telerik-scheduler
suppress
javap
mtj
anti-piracy
spec#
defensive-programming
msdev
paul-graham
ajax-forms

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App