我正在尝试通过Kotlin和JPA实现继承。我的抽象基类(用@Entity
注释)包含ID(用@Id
和@GeneratedValue
注释)和其他元数据,例如createDate等。我从Hibernate中遇到了几个错误,一个是对于除ID以外的每个字段:
org.hibernate.tuple.entity.PojoEntityTuplizer-HHH000112:惰性类的获取器不能是最终的:com.example.BaseEntity.createDate
如我所读,我需要为每个属性都包含open关键字。
我对此有3个问题:
编辑:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
abstract class BaseEntity(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0,
val createdAt: Instant = Instant.now()
)
@Entity
class SubClass(
val someProperty: String = ""
) : BaseEntity()
我正在为Gradle使用JPA插件,我相信它会创建noarg构造函数,这就是为什么我不必指定所有可为空的东西的原因。
谢谢!
答案 0 :(得分:1)
记录的错误与lazy loading有关。
在运行时休眠extends
实体以启用它。通过延迟加载实体时拦截对属性的访问来完成此操作。
科特林(Kotlin)违反了规则,默认情况下所有类都是final
。这就是我们建议添加一个open
关键字的原因。
如果属性不是open
,则休眠状态无法拦截对它的访问,因为final
方法不能被覆盖。因此是错误。
为什么不抱怨ID?
因为总是加载@Id
。无需拦截对其的访问。
没有
open
关键字似乎可以正常工作,那么为什么记录错误?
这里的关键词是似乎。它可能会引入一些细微的错误。
请考虑以下@Entity
:
@Entity
public class Book {
@Id
private Long id;
private String title;
public final Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public final String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
还有@Test
:
@Test
public void test() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// signal here
Book book = new Book();
book.setId(1L);
book.setTitle("myTitle");
entityManager.persist(book);
// noise
entityManager.getTransaction().commit();
entityManager.close();
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// signal
Book reference = entityManager.getReference(Book.class, 1L);
String title = reference.getTitle();
assertNull(title); // passes
entityManager.getTransaction().commit();
entityManager.close();
}
该测试通过,但不能通过(如果getTitle
不是final
,则会失败)。
这很难注意到
为什么在超类中必须这样做,而在子类中则不需要?我没有覆盖这些属性。
看起来像休眠的放弃时,它会看到final
@Entity
。
将open
添加到SubClass
中,您将很珍贵:
2019-05-02 23:27:27.500 ERROR 5609 --- [ main] o.h.tuple.entity.PojoEntityTuplizer : HHH000112: Getters of lazy classes cannot be final: com.caco3.hibernateanswer.SubClass.someProperty
另请参见:
PS
您忘记在@MappedSuperclass
上包含BaseEntity
吗?
没有注释,它将失败,并显示类似以下内容:
org.hibernate.AnnotationException: No identifier specified for entity: com.caco3.hibernateanswer.SubClass