Hibernate:通过持久属性的反射访问字段 [private java.lang.Integer] 时出错
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37780811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate: Error accessing field [private java.lang.Integer ] by reflection for persistent property
提问by Lev
I have strange issue when I try to get entities property:
当我尝试获取实体属性时,我遇到了奇怪的问题:
Hibernate:
select
tarifklsk0_.ID as ID1_12_0_,
tarifklsk0_.FK_TARIF as FK_TARIF2_12_0_,
tarifservp1_.FK_TARIF as FK_TARIF2_11_1_,
tarifservp1_.ID as ID1_11_1_,
tarifservp1_.ID as ID1_11_2_,
tarifservp1_.FK_TARIF as FK_TARIF2_11_2_,
tarifservp1_.N1 as N3_11_2_
from
TR.TARIFXKLSK tarifklsk0_
left outer join
TR.TARIF_SERV_PROP tarifservp1_
on tarifklsk0_.FK_TARIF=tarifservp1_.FK_TARIF
where
tarifklsk0_.ID=?
Jun 13, 2016 7:38:26 AM org.hibernate.event.internal.DefaultLoadEventListener doOnLoad
INFO: HHH000327: Error performing load command : org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Integer TarifKlsk.fkTarif] by reflection for persistent property [TarifKlsk#fkTarif] : 1027303
Exception in thread "main" org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.Integer TarifKlsk.fkTarif] by reflection for persistent property [TarifKlsk#fkTarif] : 1027303
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43)
....skipped...
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field TarifKlsk.fkTarif to java.lang.Integer
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
My entities:
我的实体:
TarifKlsk
关税
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.BatchSize;
@SuppressWarnings("serial")
@Entity
@Table(name = "TARIFXKLSK", schema="TR")
public class TarifKlsk implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", updatable = false, nullable = false)
private Integer id;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="FK_TARIF", referencedColumnName="FK_TARIF")
@BatchSize(size = 50)
private Set<TarifServProp> tarifservprop = new HashSet<TarifServProp>(0);
@Column(name = "FK_TARIF", updatable = false, nullable = false)
private Integer fkTarif;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Set<TarifServProp> getTarifservprop() {
return tarifservprop;
}
public void setTarifservprop(Set<TarifServProp> tarifservprop) {
this.tarifservprop = tarifservprop;
}
public Integer getFkTarif() {
return fkTarif;
}
public void setFkTarif(Integer fkTarif) {
this.fkTarif = fkTarif;
}
}
TarifServProp
关税服务支持
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "TARIF_SERV_PROP", schema="TR")
public class TarifServProp implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", updatable = false, nullable = false)
private Integer id;
@Column(name = "FK_TARIF", updatable = false, nullable = false)
private Integer fkTarif;
public Integer getId() {
return id;
}
@Column(name = "N1", updatable = false, nullable = false)
private Integer n1;
public void setId(Integer id) {
this.id = id;
}
public Integer getFkTarif() {
return fkTarif;
}
public void setFkTarif(Integer fkTarif) {
this.fkTarif = fkTarif;
}
public Integer getN1() {
return n1;
}
public void setN1(Integer n1) {
this.n1 = n1;
}
}
My test module:
我的测试模块:
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session sess = sf.openSession();
sess.beginTransaction();
TarifKlsk k2=sess.get(TarifKlsk.class, 1027303);
for (TarifServProp t : k2.getTarifservprop()) {
System.out.println("Tar="+t.getN1());
}
System.out.println("End init");
What am I doing wrong? I've checked all fields of these entities and all of them named properly....
我究竟做错了什么?我已经检查了这些实体的所有字段,并且所有字段都正确命名....
UpdtMy POM.xml
更新我的 POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.hibernate</groupId>
<artifactId>HibernateEHCacheExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Hibernate Secondary Level Cache Example using EHCache implementation</description>
<dependencies>
<!-- Hibernate Core API -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<!-- EHCache Core APIs -->
<!-- http://mvnrepository.com/artifact/net.sf.ehcache/ehcache-core -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.11</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.2.0.Final</version>
</dependency>
<!-- EHCache uses slf4j for logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
</project>
Upd2
更新2
I've found out that my child entity doesn't contain records with fk_tarif corresponding to the fk_tarif from master... but I think it doesn't matter, why is error exists?
我发现我的子实体不包含与来自 master 的 fk_tarif 对应的 fk_tarif 的记录......但我认为这无关紧要,为什么存在错误?
回答by AlexankrKotov
It is bug in version 5.0 and 5.1.0 https://hibernate.atlassian.net/browse/HHH-10618
这是 5.0 和 5.1.0 版本中的错误 https://hibernate.atlassian.net/browse/HHH-10618
回答by Anas Lachheb
I advice you to keep working with hibernate version 4.X.X instead of the version 5 because it's not 100% stable (more the 2000 issues).
我建议您继续使用 hibernate 4.XX 版而不是 5 版,因为它不是 100% 稳定的(更多的是 2000 个问题)。
https://hibernate.atlassian.net/projects/HHH/issues/HHH-11144?filter=allopenissues
https://hibernate.atlassian.net/projects/HHH/issues/HHH-11144?filter=allopenissues
Good luck
祝你好运
回答by onderbewustzijn
I am working with EAP7, which contains Hibernate Core {5.0.9.Final-redhat-1}
我正在使用包含 Hibernate Core {5.0.9.Final-redhat-1} 的 EAP7
I have two entities:
我有两个实体:
@Entity
@Data
@EqualsAndHashCode(callSuper = true, doNotUseGetters = true)
@ToString(callSuper = true, doNotUseGetters = true)
public class Keuze extends MainTable {
@NonNull
String naam;
@Tolerate
public Keuze() {
}
}
and
和
@Entity
@Data
@EqualsAndHashCode(callSuper = true, doNotUseGetters = true, exclude = {"gegeven", "werkJaar", "keuze", "keuzes" })
@ToString(callSuper = true, doNotUseGetters = true, exclude = { "gegeven", "werkJaar", "keuze", "keuzes" })
public class Waarde extends MainTable {
@NonNull
@ManyToOne(optional = false, fetch = FetchType.LAZY)
Gegeven gegeven;
@NonNull
@ManyToOne(optional = false, fetch = FetchType.LAZY)
WerkJaar werkJaar;
String alfanumeriek;
Integer numeriek;
BigDecimal valuta;
@Lob
String tekst;
Boolean polair;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
Keuze keuze;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
Set<Keuze> keuzes;
@Tolerate
public Waarde() {
}
}
They both extend from this class:
它们都从这个类扩展而来:
@MappedSuperclass
@Data
@Cacheable
public abstract class MainTable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Version
Long version;
}
When calling merge upon Waarde, it throws following error:
在 Waarde 上调用 merge 时,会抛出以下错误:
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [java.lang.Long vo.cjsm.monitoring.data.schema.dynamic.main.MainTable.id] by reflection for persistent property [vo.cjsm.monitoring.data.schema.dynamic.field.Keuze#id] : Keuze(super=MainTable(id=1, version=0), naam=Leesmotivatie)
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:4601)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:148)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:850)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:832)
at org.hibernate.engine.spi.CascadingActions.cascade(CascadingActions.java:260)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:431)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:363)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:468)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:327)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:170)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:69)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:840)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:822)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:827)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1161)
... 149 more
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field vo.cjsm.monitoring.data.schema.dynamic.main.MainTable.id 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)
... 171 more
By removing the ToString line of Lombok and adding my own implementation of toString by overriding the default one, the error message disappeared and the code was working back!
通过删除 Lombok 的 ToString 行并通过覆盖默认实现添加我自己的 toString 实现,错误消息消失了,代码正在恢复!
Now the entity looks like this:
现在实体看起来像这样:
@Entity
@Data
@EqualsAndHashCode(callSuper = true, doNotUseGetters = true)
public class Keuze extends MainTable {
@NonNull
String naam;
@Tolerate
public Keuze() {
}
@Override
public String toString() {
return getId().toString();
}
}
So somehow, for an unknown reason the toString method has effect on how hibernate merges the code... Don't ask me how :-) It just seems to work. I tried everything else on the web with no luck!
所以不知何故,由于未知原因 toString 方法对休眠如何合并代码有影响......不要问我如何:-) 它似乎工作。我在网上尝试了所有其他方法,但都没有成功!
Hope this helps for somebody else!
希望这对其他人有帮助!
回答by R. Cohen
I hit this same error after upgrading from Hibernate 4 to 5. At this time the hibernate bug doesn't seem to be fixed in any version up to 5.3. In my case this error happeneds while lazily fetching a collection of entity A which had an eager one-to-many relationship to B using a property from A which is not the primary key (I know, not a good relational model). It might actually be a more complicated edge case than just this, but I don't have time right now to reproduce this in a minimal test case).
从 Hibernate 4 升级到 5 后,我遇到了同样的错误。此时,hibernate 错误似乎没有在 5.3 之前的任何版本中得到修复。在我的情况下,这个错误发生在使用来自 A 的属性而不是主键(我知道,不是一个好的关系模型)懒惰地获取实体 A 的集合时,该集合与 B 具有急切的一对多关系。它实际上可能是一个比这更复杂的边缘情况,但我现在没有时间在最小的测试用例中重现它)。
In tracing through the hibernate code it appears that hibernate gets confused while trying to bind parameters for the query for B, and when it thinks its trying to get the foreign key, the property from object A, it, in fact, already has the property value. The code is treating the value as if it is the object A and ends up with the reflection error shown above.
在跟踪 hibernate 代码时,似乎 hibernate 在尝试为 B 的查询绑定参数时感到困惑,并且当它认为它试图获取外键时,对象 A 的属性,实际上,它已经具有该属性价值。代码将值视为对象 A 并以上面显示的反射错误结束。
I was able to get past this error by changing the one-to-many relationship to B to lazy. I hope this helps someone else.
通过将 B 的一对多关系更改为惰性,我能够克服这个错误。我希望这对其他人有帮助。
回答by Alex Arvanitidis
In my case the problem was that in my model the setter was auto-generated as
就我而言,问题是在我的模型中,setter 是自动生成的
public void setComments(List comments){
}
without a type. Fixed it by setting it to List<Comment> comments
没有类型。通过将其设置为修复它List<Comment> comments