无法执行 JPA 模式生成创建命令
Posted
技术标签:
【中文标题】无法执行 JPA 模式生成创建命令【英文标题】:Unable to execute JPA schema generation create command 【发布时间】:2016-01-21 03:16:42 【问题描述】:我有一个使用 Hibernate over JDBC 和 mysql 的 JPA 应用程序,没有任何应用程序服务器。
在我的 persistence.xml 中,我定义了从脚本中创建、加载和删除数据库的规则:
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="script"/>
<property name="javax.persistence.schema-generation.create-script-source" value="META-INF/scripts/create.sql" />
<property name="javax.persistence.sql-load-script-source" value="META-INF/scripts/load.sql" />
<property name="javax.persistence.schema-generation.drop-source" value="script" />
<property name="javax.persistence.schema-generation.drop-script-source" value="META-INF/scripts/drop.sql" />
但是,当执行 Maven 测试目标时,我收到以下错误:
[CREATE TABLE country (]
堆栈跟踪看起来像这样:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2470)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2617)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2546)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2504)
at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:840)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:740)
at org.hibernate.jpa.internal.schemagen.GenerationTargetToDatabase.acceptCreateCommands(GenerationTargetToDatabase.java:44)
... 34 more
加载脚本从创建国家表开始:
DROP DATABASE IF EXISTS bookstore;
CREATE DATABASE bookstore;
USE bookstore;
CREATE TABLE country (
id INT(10) UNSIGNED AUTO_INCREMENT NOT NULL,
name VARCHAR(50) NOT NULL,
code VARCHAR(2) NOT NULL UNIQUE,
description VARCHAR(1000),
KEY (id)
);
ALTER TABLE country ADD CONSTRAINT pk_country_id PRIMARY KEY (id);
Country类映射在persistence.xml文件中,源码如下。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "country")
public class Country extends ro.pub.cs.aipi.lab02.entities.Entity
protected Long id;
protected String name;
protected String code;
protected String description;
public Country()
public Country(String name, String code, String description)
this.name = name;
this.code = code;
this.description = description;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public Long getId()
return id;
public void setId(Long id)
this.id = id;
@Column(name = "name")
public String getName()
return name;
public void setName(String name)
this.name = name;
@Column(name = "code")
public String getCode()
return code;
public void setCode(String code)
this.code = code;
@Column(name = "description")
public String getDescription()
return description;
public void setDescription(String description)
this.description = description;
persistence.xml 文件中的 Hibernate 属性如下:
<property name="hibernate.connection.pool_size" value="1"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.id.new_generator_mappings" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="true"/>
我尝试将 hibernate.dialect 更改为 org.hibernate.dialect.MySQL5InnoDBDialect 并从 Entity 类中删除 @Table 注释,但我没有注意到行为有任何变化。
【问题讨论】:
【参考方案1】:我最终设法弄明白了。似乎hibernate每行只需要一个语句,因为在我的例子中,脚本是格式化的,它只占用了语句的第一行,因此不完整。
重新格式化脚本并将命令放在一行中解决了这个问题。
【讨论】:
建议您将其报告为 hibernate 中的错误,因为其他 JPA 实现可以很好地处理此类脚本延续【参考方案2】:尝试设置值 last 属性,选择以下“create”、“update”、“create-drop”、validate 之一。
【讨论】:
javax.persistence.schema-generation.database.action
与问题无关..【参考方案3】:
如果您的 JPA 提供程序处于休眠状态,您可以在 persistence.xml 中使用以下属性来允许多行语句:
<property name="hibernate.hbm2ddl.import_files_sql_extractor" value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor" />
【讨论】:
srsly?!我不敢相信这不是默认行为。我无法相信它浪费了我多少时间。 srsly... 不能再同意了以上是关于无法执行 JPA 模式生成创建命令的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 Spring Data JPA 执行聚合函数并获取结果