无法将 java.lang.String 字段设置为 java.lang.String

Posted

技术标签:

【中文标题】无法将 java.lang.String 字段设置为 java.lang.String【英文标题】:Can not set java.lang.String field to java.lang.String 【发布时间】:2016-01-23 01:56:51 【问题描述】:

我目前正在开发一个带有套接字服务器的小型 MMO 应用程序。我使用的数据库是 PostgreSQL,我使用的是 Hibernate ORM。 在请求单个用户拥有的所有头像时,我偶然发现了一个例外。

我参加了 3 个课程,分别是:

游戏服务器客户端 数据库 数据库.查询

当用户(客户端应用程序)通过套接字向服务器发送请求时,会调用一个方法,该方法应返回所有头像的 JsonString。

然而,使用 HQL 查询 from UserOwnsAvatar where user = :username 并将结果放入 UserOwnsAvatar 对象的 ArrayList 中,它会返回一个 Can not set java.lang.String field nl.marcusink.mmo.server.database.table.User.username to java.lang.String

完整的堆栈跟踪是:

org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.String nl.marcusink.mmo.server.database.table.User.username] by reflection for persistent property [nl.marcusink.mmo.server.database.table.User#username] : Mjollnir94
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223)
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4594)
    at org.hibernate.type.EntityType.toLoggableString(EntityType.java:505)
    at org.hibernate.internal.util.EntityPrinter.toString(EntityPrinter.java:87)
    at org.hibernate.engine.spi.QueryParameters.traceParameters(QueryParameters.java:281)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:194)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1268)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
    at nl.marcusink.mmo.server.database.Database$Queries.avatarsRequest(Database.java:134)
    at nl.marcusink.mmo.server.connection.GameServerClient.run(GameServerClient.java:91)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field nl.marcusink.mmo.server.database.table.User.username to java.lang.String
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:393)
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39)
    ... 11 more

查询代码为:

Query query = session.createQuery("from UserOwnsAvatar where user = :username");
query.setParameter("username", username);
ArrayList<UserOwnsAvatar> ownedAvatars = (ArrayList<UserOwnsAvatar>) query.list();

最后一行是错误的原因,有什么想法吗?

编辑

@Id
@ManyToOne(targetEntity = User.class)
@JoinColumn(name = "username", nullable = false)
private User user;

@Id
@OneToOne(targetEntity = Avatar.class)
@JoinColumn(name = "avatar", nullable = false, unique = true)
private Avatar avatar;

这里的用户名等于User对象的用户名,即:

@Id
@Column(name = "username", unique = true, nullable = false)
private String username;

【问题讨论】:

能否请您出示与username相关的代码... 也许您需要将public void setUsername(String username) this.username = username; 添加到User 类中。 我为每个表类生成了所有的 getter 和 setter。 public void setUsername(String username) this.username = username; 就是其中之一。这不可能是我认为的问题 别介意我纠正自己:查询:user tablefield:username 哦,那个错误信息是一团糟。从堆栈跟踪中可以看出,它尝试get,但会产生错误消息“无法设置”。在查看UnsafeFieldAccessorImpl .ensureObj 的源代码后,我得出结论,尽管错误消息侧重于值,但它是 instance,在其上进行了尝试,而不是 @987654335 类型@… 【参考方案1】:

您必须设置完整的(或仅具有相关字段的对象)而不是该对象的一个​​特定值。

我的理解是您在设置参数时尝试设置String,但该列的类型为User。 Hibernate 正在尝试在 String 上调用 getUsername 方法,这就是错误的原因。

所以把你的代码改成这样:

User user = getSomeUser();
Query query = session.createQuery("from UserOwnsAvatar where user.username =  :username");
query.setParameter("username", user);

【讨论】:

您的想法是正确的,但您的示例代码需要修改。它解决了我遇到的类似问题。【参考方案2】:

user = :username 不正确。 user 不是实体的字符串字段。使用联接或使用休眠条件为用户创建别名并添加限制,例如 .add(Restriction.eq("user.username",username)。

【讨论】:

以上是关于无法将 java.lang.String 字段设置为 java.lang.String的主要内容,如果未能解决你的问题,请参考以下文章

DBunit 生成 java.lang.ClassCastException:尝试加载 CLOB 字段时无法将 java.lang.String 强制转换为 oracle.sql.CLOB

Spring - 无法将java.lang.String类型的属性值转换为必需类型java.util.Date

无法将类型 [java.lang.String] 的属性值转换为所需类型 [java.lang.Integer]

无法将 java.lang.String 类型的对象转换为类型 - FirebaseUI

如何修复错误:无法将类型“java.lang.String”的值转换为所需类型“java.lang.Long”;

无法将 java.lang.String 类型的对象转换为 com.example 类型