JPA-Hibernate - “无法通过继承的反射getter获取字段值

时间:2014-07-10 08:59:25

标签: java hibernate jpa

我有一个实体是某些实体的基类。

@Entity
@Table(name = "resource")
@Inheritance(strategy = InheritanceType.JOINED)
public class Resource implements Serializable{

}

我有一些从资源延伸的子类。

@Entity
@Table(name = "ResourceWithA")
@PrimaryKeyJoinColumn(name = "ResourceWithA_id")
public class ResourceWithA extends Resource implements Serializable, AInterface{

    @Column
    private boolean inService;
    @Override
    public void setInService(boolean inService) {
        this.inService = inService;
    }

    @Override
    public boolean getInService() {
       return inService;
    }

}

@Entity
@Table(name = "ResourceWithB")
@PrimaryKeyJoinColumn(name = "ResourceWithB_id")
public class ResourceWithB extends ResourceWithA implements Serializable{

}

当我想插入数据时,我会得到以下例外情况。我没有仅在inService属性中获得此异常.Class还有一些其他属性,如Collection,它们也有问题

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.ResourceWithB.inService
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:695)
at com.test.persistence.ConnectionTest.saveData(ConnectionTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.ResourceWithB.inService
at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:62)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValues(AbstractEntityTuplizer.java:485)
at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValues(PojoEntityTuplizer.java:243)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValues(AbstractEntityPersister.java:3834)
at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:600)
at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:337)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:303)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:258)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:869)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851)
at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:279)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476)
at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:388)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:303)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:258)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:859)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:847)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:686)
... 24 more
Caused by: java.lang.IllegalArgumentException: Can not set boolean field com.ResourceWithA.inService to com.Resource
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeBooleanFieldAccessorImpl.getBoolean(UnsafeBooleanFieldAccessorImpl.java:22)
at sun.reflect.UnsafeBooleanFieldAccessorImpl.get(UnsafeBooleanFieldAccessorImpl.java:18)
at java.lang.reflect.Field.get(Field.java:358)
at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:59)
... 51 more

EDITTED: setter和getter方法。正如我所说,这个问题与inService字段无关。如果我将其注释为@Transient,则会为其他字段抛出相同的异常。

public interface AInterface {
    public void setInService(boolean inService);

    public boolean getInService();
}

已编辑:我注意到了这个案例。我有一个容器类,用于存储资源列表。 有一些级联定义,

public class Container{
@Id
@GeneratedValue
@Column(name = "container_id")
private long id; // unique identifier
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "container_resources", joinColumns = {
    @JoinColumn(name = "container_id", referencedColumnName = "container_id")
}, inverseJoinColumns = {
    @JoinColumn(name = "id", referencedColumnName = "id")
})
/** list of resources inside power system. */
private Collection<Resource> resources = new HashSet<Resource>();

}

我正在对Container进行保存操作。 em.merge(容器)。

如果资源中有一种资源,则不存在任何问题。如果我有多种资源类型,我会设置/获取反射错误。

2 个答案:

答案 0 :(得分:0)

您可以使用继承注释ResourceWithA

@Entity
@Table(name = "ResourceWithA")
@PrimaryKeyJoinColumn(name = "ResourceWithA_id")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class ResourceWithA extends Resource implements Serializable, AInterface{

答案 1 :(得分:0)

正如我在问题描述中提到的,我使用的是em.merge。当我使用persist时,问题就解决了。但我不知道解决方案背后的真正原因是什么。