我正在尝试使用75.3 Initialize a database using Spring JDBC之后的视图和规则初始化我的数据库。
75.3使用Spring JDBC初始化数据库
Spring JDBC具有DataSource初始化程序功能。 Spring Boot默认启用它,并从标准位置schema.sql和data.sql(在类路径的根目录中)加载SQL。另外,Spring Boot将加载模式 - $ {platform} .sql和data - $ {platform} .sql文件(如果存在),其中platform是spring.datasource.platform的值,例如:您可以选择将其设置为数据库的供应商名称(hsqldb,h2,oracle,mysql,postgresql等)。 Spring Boot默认启用Spring JDBC初始化程序的快速失败功能,因此如果脚本导致异常,则应用程序将无法启动。可以通过设置spring.datasource.schema和spring.datasource.data来更改脚本位置,如果spring.datasource.initialize = false,则不会处理任何位置。
本节说如果我放一个schema-postgresql.sql
,它应该使用该文件包含的脚本初始化我的数据库。
不幸的是,脚本以以下错误结束
引起:org.postgresql.util.PSQLException:输入SQL状态结束时的语法错误 位置: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] 在org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:217)〜[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7] 在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] 在org.postgresql.jdbc.PgStatement.execute(PgStatement.java:310)〜[postgresql-9.4.1209.jre7.jar:9.4.1209.jre7] 在org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:473)〜[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE] ...省略了64个常见帧
但是,如果我从pgAdminIII
运行此脚本,则没有错误,并且创建具有相应规则的视图没有任何问题。
我在这里做错了什么?
这是我的Spring Boot示例的结构,用于重现它。
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 = "";
}
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;
}
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;
}
package com.example.model;
public enum Role {
ADMIN, USER;
}
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);
}
}
#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
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);
);
<?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>
整个代码可以从here下载。
根据poz's comment我将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 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();
但它会产生另一个错误,就像预测一样。
错误:未终止的引用字符串位于或附近“$$ BEGIN INSERT INTO person(id,name,surname)VALUES(new.id,new.name,new.surname)”
答案 0 :(得分:0)
因为pozs没有发布自己的答案而且已经过了一段时间我自己就是这样做了。
将CREATE RULE
更改为INSTEAD OF
触发$$
- 引用'
- 引用解决了问题。唯一的问题是我必须逃避函数定义中的所有撇号。虽然不是那么大的痛苦。