[编辑:将 q 中的弹簧版本固定到 5.2.9。v2.3.4 是聚合的 Maven 开发。]
我已经通过大量帖子试图弄清楚这一点。似乎存在一个巨大的兼容性问题,但我无法弄清楚要更改为哪些版本。我通常不做Java,但在教学时必须这样做,所以希望有人会忽略我不存在的Java技能并给我一些建议。♂️</p>
如果我单步执行反汇编代码,我可以看到我的单元测试(集成)在尝试反映我的 ID 属性时会做其他事情,而不是使用 Spring 运行时所做的事情。
[编辑] 这是 SQL 日志:
Hibernate: create table ChatMessages (Id varchar(255) not null, UserName varchar(50), Message varchar(512), primary key (Id))
2020-10-07 10:01:15.142 INFO 43304 --- [nio-8081-exec-8] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select chatmessag0_.Id as Id1_0_, chatmessag0_.UserName as UserName2_0_, chatmessag0_.Message as Message3_0_ from ChatMessages chatmessag0_
这是异常和跟踪的顶部:
[nio-8081-exec-6] o.h.p.access.spi.GetterMethodImpl : HHH000122: IllegalArgumentException in class: org.hiof.chatroom.core.ChatMessage, getter method of property: id
2020-10-07 02:28:59.438 ERROR 47504 --- [nio-8081-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of org.hiof.chatroom.core.ChatMessage.id] with root cause
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_172]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_172]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_172]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_172]
at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:41) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4633) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.id.Assigned.generate(Assigned.java:32) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:105) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:682) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
at org.hiof.chatroom.database.ChatMessageRepository.add(ChatMessageRepository.java:21) ~[classes/:na]
这是一个使用 SQL Lite 的超级简单的数据库设置。
唯一的实体是这样映射的:
<class name="org.hiof.chatroom.core.ChatMessage" table="ChatMessages">
<id name="id" column="Id">
<generator class="assigned"/>
</id>
<property name="user" column="UserName" length="50"/>
<property name="message" column="Message" length="512"/>
</class>
和实体:
public class ChatMessage {
private String id;
private String user;
private String message;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
这是一个测试,没有不同的基础设施和配置,而不是(没有)让 Spring 运行应用程序:
public class When_persisting_chat_messages {
@Test
public void stores_message() throws Exception {
DatabaseManager.ensureDatabase("./db/chat-test.db");
UnitOfWork uow = new UnitOfWork();
ChatMessageRepository repo = new ChatMessageRepository(uow);
ChatMessage msg = new ChatMessage();
String id = UUID.randomUUID().toString();
msg.setId(id);
repo.add(msg);
uow.saveChanges();
uow.close();
uow = new UnitOfWork();
repo = new ChatMessageRepository(uow);
msg = repo.get(id);
Assertions.assertNotNull(msg);
}
}
我相当确定这与在我的UOWStandardServiceRegistryBuilder
中设置会话工厂有关。不知道该怎么做。
太晚了,我希望明天为一些学生演示这个,所以如果我离开这篇文章有点偏离 SO 的首选标准,我深表歉意。
[编辑]
回购在这里发布:https ://github.com/lars-erik/hiof-sweat2020-chatroom-demo
[2 天后编辑]
我设法确定了它在 Web 项目中运行时抛出的位置。对于像我这样的 dotnet 开发人员,这闻起来就像我的核心“程序集”(模块)的两个版本被加载到“域”中,并且 ID 属性是从“错误模块的元数据”中读取的。不知道,但看起来就是这样。在该getIdentifier
方法中,owner 和 idGetter 都指向同一个类,org.hiof.chatroom.core.ChatMessage
. 然而,invoke
坚持实例不是 id getter 的声明类。这是跟踪:
get:42, GetterMethodImpl (org.hibernate.property.access.spi)
getIdentifier:230, AbstractEntityTuplizer (org.hibernate.tuple.entity)
getIdentifier:5155, AbstractEntityPersister (org.hibernate.persister.entity)
generate:31, Assigned (org.hibernate.id)
saveWithGeneratedId:115, AbstractSaveEventListener (org.hibernate.event.internal)
saveWithGeneratedOrRequestedId:194, DefaultSaveOrUpdateEventListener (org.hibernate.event.internal)
saveWithGeneratedOrRequestedId:38, DefaultSaveEventListener (org.hibernate.event.internal)
entityIsTransient:179, DefaultSaveOrUpdateEventListener (org.hibernate.event.internal)
performSaveOrUpdate:32, DefaultSaveEventListener (org.hibernate.event.internal)
onSaveOrUpdate:75, DefaultSaveOrUpdateEventListener (org.hibernate.event.internal)
accept:-1, 1659093435 (org.hibernate.internal.SessionImpl$$Lambda$541)
fireEventOnEachListener:102, EventListenerGroupImpl (org.hibernate.event.service.internal)
fireSave:636, SessionImpl (org.hibernate.internal)
save:629, SessionImpl (org.hibernate.internal)
save:624, SessionImpl (org.hibernate.internal)
[编辑十月。11.] 使用 spring 运行时,调试当前显示 ChatMessage 类的两个版本。:/
owner.getClass() = {Class@9587} "class org.hiof.chatroom.core.ChatMessage"
owner.getClass() == getterMethod.getDeclaringClass() = false
org.hiof.chatroom.core.ChatMessage.class = {Class@8446} "class org.hiof.chatroom.core.ChatMessage"
getterMethod.getDeclaringClass() = {Class@8446} "class org.hiof.chatroom.core.ChatMessage"
所有者类的类加载器是“RestartClassLoader”,而声明类加载器是“Launcher$AppClassLoader”。