【问题标题】:EclipseLink "create-or-extend-tables" not working: "...unknown column..."EclipseLink“创建或扩展表”不起作用:“......未知列......”
【发布时间】:2012-11-02 13:24:54
【问题描述】:

我将 EclipseLink 2.4.1 与 Glassfish 和 MySQL 数据库一起用于持久化实体。
我向实体添加了一个字段,当我尝试保留该实体时,它说新字段是“未知”。
我们应该如何使用新的“创建或扩展表”功能?我原以为它会为这个字段创建一个新列。

以下是一些相关信息,如果您需要更多信息,请告诉我。

提前致谢!

堆栈跟踪

...
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003 ad44345): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 't0.TESTFIELD' in 'field list'
Error Code: 1054
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
...

persistence.xml

<persistence-unit name="myApp" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/mysql</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<properties>
  <property name="eclipselink.ddl-generation.output-mode" value="database"/>
  <property name="eclipselink.jdbc.batch-writing" value="Buffered"/>
  <property name="eclipselink.logging.level" value="INFO"/>
  <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
</properties>

额外信息

drop-and-create-tables 确实有效。
我正在使用 merge(entity) 来持久化新实体(因为它们有很多多对一的字段,否则会导致重复的主 ID 问题) - 我觉得这可能是问题所在。
查看 MySQL 日志以及来自 EclipseLink 的最佳日志级别,EclipseLink 首先尝试从数据库中选择实体,如下所示:
mysql_log:

121115 10:49:03 9 Query SELECT t0.LISTINGID, t0.DTYPE, ... , t0.TESTFIELD FROM the_entity...

这是最后一个 mysql 日志条目,这意味着它在这里崩溃,它从不尝试删除表等。这是否意味着您不能将合并与 drop-and-create 或 create-or-extend 一起使用?我刚google了一下,没有找到任何相关信息。

EclipseLink 日志记录:

FINER: client acquired: 64279491
FINER: TX binding to tx mgr, status=STATUS_ACTIVE
FINER: acquire unit of work: 161130796
FINEST: Merge clone with references nz.co.site.api.v1.ListedItemDetail@8d88ca1
FINEST: Execute query ReadObjectQuery(referenceClass=ListedItemDetail )
FINEST: Connection acquired from connection pool [read].
FINEST: reconnecting to external connection pool
FINE: SELECT t0.LISTINGID, t0.DTYPE, ... , t0.TESTFIELD, ... , FROM ITEM t0, LISTEDITEMDETAIL t1 WHERE ((t0.LISTINGID = ?) AND ((t1.LISTINGID = t0.LISTINGID) AND (t0.DTYPE = ?)))
bind => [2 parameters bound]
FINE: SELECT 1
FINEST: Connection released to connection pool [read].
WARNING: Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.DatabaseException

我使用 bean 事务管理来合并新实体:

userTransaction.begin();
entityManager.merge(entity);
entityManager.flush();
userTransaction.commit();

【问题讨论】:

  • 您能否发布新映射并将日志记录设置为最佳并显示生成的 DDL?是否可以使用 drop-and-create-tables 代替?
  • 不,drop-and-create-tables 也不起作用!抱歉,我不确定您所说的新映射是什么意思?你的意思是新的实体类?我在问题的底部添加了一些额外的信息。
  • 您需要将日志记录转到更高级别以查看在数据库中执行的 DDL 以确定发生了什么问题,因为 DDL 异常不是致命的,并且不会在 INFO 级别中写入.尝试将其设置为 FINE 或 FINEST:

标签: jakarta-ee jpa glassfish eclipselink


【解决方案1】:

Glassfish 拦截 eclipselink.ddl-generation.output-mode 属性并强制将其写入文件,如此处的答案所述:eclipselink does not generate tables from annotated JPA classes 因此,您需要检查是否已在 Glassfish 中启用 java2db 以使“drop-and-create-tables”正常工作。

“create-or-extend-tables”虽然需要数据库连接才能查看数据库中的内容,因此目前不适用于 sql-script 输出模式。我不确定如何强制 Glassfish 不覆盖 output-mode 属性,但如果无法做到,您将需要运行持久性单元端 glassfish 才能使用此功能。

glassfish 中的一种解决方法是尝试以下方法:

Map properties = new HashMap();
properties.put(PersistenceUnitProperties.DDL_GENERATION, PersistenceUnitProperties.CREATE_OR_EXTEND);
//create-or-extend only works on the database
properties.put(PersistenceUnitProperties.DDL_GENERATION_MODE, PersistenceUnitProperties.DDL_DATABASE_GENERATION);
//this causes DDL generation to occur on refreshMetadata rather than wait until an em is obtained
properties.put(PersistenceUnitProperties.DEPLOY_ON_STARTUP, "true");
JpaHelper.getEntityManagerFactory(em).refreshMetadata(properties);

【讨论】:

  • 感谢您的快速回答!有点太快了,我添加额外信息的时间比你回复的时间长,所以你可能想看看我问题的底部。我认为这个问题可能与我正在合并的事实有关,因此它首先执行一个 select 语句,但由于该字段不在数据库中而失败。你会得出同样的结论吗?如果是,你知道解决办法吗?
  • 澄清一下,如果我不添加新字段,drop-and-create-tables 就可以工作。在部署时,它会删除所有表并重新创建它们。
  • 该错误表明该字段不存在,因此不是合并问题。如果不添加新字段,我不确定您所说的 drop+create 工作是什么意思。它适用于部署,那么您如何向您的实体添加一个它不起作用的字段?不是重新部署了吗?
  • 很抱歉这么久才回复,我有点放弃了,因为它占用了时间。我刚刚回去查看它,至少目前看来,'create-or-extend-tables' 似乎没有做任何事情,就像它不受支持一样。它不会在部署时删除、创建或扩展任何表。更改为 create-tables 或 drop-and-create-tables 可以正常工作。根据日志,EclipseLink 版本为 2.4.1。这将解释我遇到的所有问题(尽管我原以为我会注意到),因为它会在合并期间尝试选择一个不存在的字段。
  • 如答案中所述,Glassfish 基于其 java2db 功能注入 eclipselink 属性。如果打开,它将 ddl-generation 模式设置为 drop-and-create-tables,如果关闭,则将其设置为 none。它完全覆盖用户指定的属性值。我看到让“创建或扩展表”工作的唯一方法是在 glassfish 之外运行持久性单元。请提交 glassfish 错误/增强,因为应该有办法让 EclipseLink 处理 DDL。
猜你喜欢
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2022-10-19
  • 2013-10-25
相关资源
最近更新 更多