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

Beginner - Java extends
The best way to assemble Swagger documentation from multiple REST endpoints
Deleting and adding objects to list while iterating
spring boot application in cluster
FileInputStream class method read(byte[ ] b) how that works?
Log4j: values not shown on console
Get data from COM4 using Javax.comm
Command for Total Average CPU LOAD in real time
How do I move a multidimensional array into another method?
Unable to turn off logging in console in logback
How to use navigateToRow() and findRow() of HtmlDataTable in icefaces 1.8
Differents between SDA and DDA in JavaCard?
Simple mapping configuration List<Object> field
Declare Generic Type for class based on method parameter
ClassCastException: ArrayList cannot be cast to
Spring Roo 1.3.2 And Java 8

Categories

HOME
compiler-construction
client
mediawiki
layout
react-redux
alpha
in-app-purchase
qore
amazon-cloudformation
quicklook
caml
dosgi
libtiff
ef-migrations
propel
http-status-code-504
code-review
reverse-proxy
riot.js
scriptcs
jasonette
icloud-api
android-widget
opennlp
facebook-access-token
intel-pin
brunch
info.plist
tooltipster
minitab
neo4j-spatial
windows-server-2000
objectanimator
delicious-api
bluestacks
stormpath
twilio-api
http-get
asset-pipeline
textmate
http-referer
mmenu
simplexml
dartium
multilingual
theano.scan
hilbert-curve
sqlite2
hue
cookiecutter-django
grid.mvc
google-closure
firebase-admin
fakeiteasy
thin
cubic-spline
strptime
qsslsocket
jquery-validate
fancybox-2
aurelia-validation
colorama
kbuild
sqldf
iso8601
google-cdn
root-framework
adxstudio-portals
multi-level
lttng
react-native-listview
hover-over
design-by-contract
rhino-servicebus
tform
wordml
citrus-pay
quicklisp
ibaction
operation
unity3d-gui
notify
truevault
directoryservices
clicktag
gui-test-framework
android-imagebutton
codeigniter-routing
wordpress-theme-customize
device-manager
websocket4net
zend-route
dml
fluentautomation
marmalade
undefined-reference
meteor-velocity
app42
back-stack
orchardcms-1.7
smtp-auth
distutils
tinn-r
itmstransporter
dice
first-responder
propertyeditor
gnustep
gcj
oncheckedchanged
html-input
zend-translate
filtered-index
iweb
photoshop-cs4
backcolor
procedural-music
msdev
3gp

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