Hibernate:通过持久属性的反射访问字段 [private java.lang.Integer] 时出错

Posted

技术标签:

【中文标题】Hibernate:通过持久属性的反射访问字段 [private java.lang.Integer] 时出错【英文标题】:Hibernate: Error accessing field [private java.lang.Integer ] by reflection for persistent property 【发布时间】:2016-06-13 01:47:14 【问题描述】:

我在尝试获取实体属性时遇到了奇怪的问题:

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)       

我的实体:

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;
    


我的测试模块:

    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");

我做错了什么?我已经检查了这些实体的所有字段,并且所有这些字段都正确命名....

更新 我的 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>

更新2

我发现我的子实体不包含 fk_tarif 对应于 master 的 fk_tarif 的记录...但我认为没关系,为什么会存在错误?

【问题讨论】:

这很奇怪,但是当我将 Hibernate 版本设置为 4.1.9.Final 时,我的代码运行良好: ***** ***** Fetch Count=0 Second Level Hit Count=0二级未命中计数=0 二级放置计数=0 完成!可能是更高版本休眠版本 4.1.9 中的错误? 该解决方案帮助我解决了这个错误。我也希望你。 ***.com/questions/24693853/… 如果有帮助,我在 Spring Boot 2 + Hibernate 5 应用程序中遇到了同样的错误。这个错误是由 spring devtools starter 引起的。如果认为这有点与实时重新加载有关。 【参考方案1】:

这是版本 5.0 和 5.1.0 中的错误 https://hibernate.atlassian.net/browse/HHH-10618

【讨论】:

仍然是 5.2.0-FINAL 中的一个错误。我通过恢复到 4.3.11-FINAL 来解决。【参考方案2】:

我建议您继续使用休眠版本 4.X.X 而不是版本 5,因为它不是 100% 稳定的(超过 2000 年的问题)。

https://hibernate.atlassian.net/projects/HHH/issues/HHH-11144?filter=allopenissues

祝你好运

【讨论】:

【参考方案3】:

我正在使用 EAP7,它包含 Hibernate Core 5.0.9.Final-redhat-1

我有两个实体:

@Entity
@Data
@EqualsAndHashCode(callSuper = true, doNotUseGetters = true)
@ToString(callSuper = true, doNotUseGetters = true)
public class Keuze extends MainTable 

@NonNull
String naam;

@Tolerate
public Keuze() 



@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() 



它们都是从这个类扩展而来的:

@MappedSuperclass
@Data
@Cacheable
public abstract class MainTable 

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;

@Version
Long version;


在 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$6.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

通过删除 Lombok 的 ToString 行并通过覆盖默认设置添加我自己的 toString 实现,错误消息消失了,代码正在恢复!

现在实体看起来像这样:

@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();



不知何故,由于未知原因,toString 方法对休眠如何合并代码产生了影响……不要问我如何 :-) 它似乎有效。我在网上尝试了所有其他方法,但没有成功!

希望这对其他人有帮助!

【讨论】:

【参考方案4】:

从 Hibernate 4 升级到 5 后,我遇到了同样的错误。此时,直到 5.3 的任何版本似乎都没有修复 hibernate 错误。在我的情况下,这个错误发生在使用来自 A 的不是主键的属性(我知道,这不是一个好的关系模型)懒惰地获取与 B 具有急切一对多关系的实体 A 的集合时。它实际上可能是一个比这更复杂的边缘案例,但我现在没有时间在最小的测试案例中重现它)。

在跟踪 hibernate 代码时,hibernate 似乎在尝试为 B 的查询绑定参数时感到困惑,当它认为它试图从对象 A 获取外键、属性时,它实际上已经有属性值。代码将值视为对象 A 并以上面显示的反射错误结束。

我能够通过将与 B 的一对多关系更改为惰性来克服此错误。我希望这对其他人有帮助。

【讨论】:

【参考方案5】:

在我的情况下,问题是在我的模型中,setter 是自动生成的

public void setComments(List comments)

没有类型。通过将其设置为List&lt;Comment&gt; comments 来修复它

【讨论】:

以上是关于Hibernate:通过持久属性的反射访问字段 [private java.lang.Integer] 时出错的主要内容,如果未能解决你的问题,请参考以下文章

访问字段时出错(使用 Hibernate/JPA)

sgg_3_hibernate详解

hibernate 常识

Hibernate中的持久化类

Hibernate知识点复习之二

持久层框架(Hibernate)一