添加带有 JPA 注释的现有方法签名的接口会破坏 Eclipselink
Posted
技术标签:
【中文标题】添加带有 JPA 注释的现有方法签名的接口会破坏 Eclipselink【英文标题】:Adding interface with existing method signature that is annotated with JPA breaks Eclipselink 【发布时间】:2015-11-27 12:13:32 【问题描述】:长期以来,我有以下具有持久性的类使用JPA和Eclipselink作为持久性提供者,它们被成功持久化和查询。
ProductKeyImpl:
@Entity
@Table(name = "PRODUCT_KEY")
@Access(PROPERTY)
public class ProductKeyImpl implements ProductKey
...
派生类 SomeProductKeyImpl:
@Entity
public class SomeProductKeyImpl
extends ProductKeyImpl
implements SomeProductKey
private String accoStockCode = null;
....
@Column(name = "KEY_3")
public String getAccoStockCode()
return this.accoStockCode;
实现接口SomeProductKey:
public interface SomeProductKey extends ProductKey
String getAccoStockCode();
在重构期间,方法 getAccoStockCode()
被移动到由 SomeProductKey
实现的新接口 HasAccoStockCode
:
public interface HasAccoStockCode
String getAccoStockCode();
和
public interface SomeProductKey extends ProductKey, HasAccoStockCode
// getAccoStockCode() removed
自此更改以来,查询失败,因为显然 Eclipselink 不仅将 accoStockCode 到 KEY_3 的带注释映射添加到 SQL,而且还添加了来自 HasAccoStockCode 的 getAccoStockCode 方法的默认映射:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.1.v20150916-55dc7c3): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "ACCOSTOCKCODE": ungültiger Bezeichner
Error Code: 904
Call: SELECT ..., ACCOSTOCKCODE, KEY_3 ... FROM PRODUCT_KEY WHERE (ID = ?)
正确的选择语句不应包含 ACCOSTOCKCODE,因为该属性映射到 KEY_3
我在 Eclipselink 2.4.2 上也看到了相同的行为。万一重要,代码在 Java 7 上的 Weblogic 12.1.2 上运行。
除了恢复重构之外我还能做什么?
在@Chris 提问后编辑: 如果我从接口中删除 getAccoStockCode() ,仍然会发生相同的错误(对我来说出乎意料......)。 您的问题将我引向另一个测试用例。 JPQL
SELECT a FROM SomeProductKeyImpl a WHERE a.oid = :id
用 SQL 执行就好了
SELECT ID, PRODUCT_KEY_SUBCLASS_CODE, TIME_STAMP, KEY_3, KEY_4, KEY_2, KEY_1 FROM VRPBOOKING.PRODUCT_KEY WHERE ((ID = ?) AND (PRODUCT_KEY_SUBCLASS_CODE = ?))
bind => [123, SPK]
如果我使用 JPQL 查询超类
SELECT a FROM ProductKeyImpl a WHERE a.oid = :id
生成的SQL是
SELECT ID, PRODUCT_KEY_SUBCLASS_CODE, TIME_STAMP, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, ACCOSTOCKCODE FROM VRPBOOKING.PRODUCT_KEY WHERE (ID = ?)
bind => [123]
失败了。
【问题讨论】:
只是为了澄清,如果从所有接口中删除 getAccoStockCode() 方法,这是否有效?如果您使用 JPQL 中的 accoStockCode 执行查询,会生成什么? 【参考方案1】:问题解决了,其实不是 Eclipselink 的问题,而是开发者的问题。我们有另一个类 SomeOtherProductKeyImpl 已更改为实现接口,但没有 getAccoStockCode() 的注释。注释后,一切正常。 再次感谢 @Chris 提出的问题导致解决方案。
【讨论】:
以上是关于添加带有 JPA 注释的现有方法签名的接口会破坏 Eclipselink的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA 审计不适用于带有 @Modifying 注释的 JpaRepository 更新方法,为啥?
[ SSH框架 ] Hibernate框架学习之四(JPA)