2017-08-04 153 views
1

我用彈簧引導1.5.3帶有彈簧數據JPA,在兩個實體,其既具有JPA Annoatation ElementCollection上cloumn tagsnicknames,Hibernate會自動根據實體生成表。請參閱Job.java表的默認CollectionTable是主鍵job_id但我更改爲job_name,集合tags可以爲空。即發生異常時。休眠ElementCollection(取= FetchType.EAGER)導致的PropertyAccessException

招聘命名作業2沒有任何標記,這意味着Settags是empty.when我用jobDao.findOne(3);獲得作業2,休眠拋出異常org.hibernate.property.access.spi.PropertyAccessException Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field hello.entity.Job.name to java.lang.Integer

當我改變@ElementCollection(取= FetchType.EAGER)to @ElementCollection(fetch = FetchType.LAZY),一切都很順利。但我不知道爲什麼會FetchType.EAGER導致異常,當一個實體不其收藏column.And有元素,即使休眠應該知道使用名稱代替ID,它仍然嘗試轉換job.namejob.id 全堆棧跟蹤是

org.springframework.orm.jpa.JpaSystemException: Error accessing field [private java.lang.String hello.entity.Job.name] by reflection for persistent property [hello.entity.Job#name] : 3; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.String hello.entity.Job.name] by reflection for persistent property [hello.entity.Job#name] : 3 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
    at com.sun.proxy.$Proxy115.findOne(Unknown Source) 
    at hello.ApplicationTests.testJob2(ApplicationTests.java:67) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
Caused by: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private java.lang.String hello.entity.Job.name] by reflection for persistent property [hello.entity.Job#name] : 3 
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:43) 
    at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:58) 
    at org.hibernate.type.ComponentType.getPropertyValue(ComponentType.java:419) 
    at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242) 
    at org.hibernate.engine.spi.CollectionKey.generateHashCode(CollectionKey.java:64) 
    at org.hibernate.engine.spi.CollectionKey.<init>(CollectionKey.java:58) 
    at org.hibernate.engine.spi.CollectionKey.<init>(CollectionKey.java:43) 
    at org.hibernate.engine.loading.internal.CollectionLoadContext.getLoadingCollection(CollectionLoadContext.java:95) 
    at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.finishUpRow(CollectionReferenceInitializerImpl.java:105) 
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:121) 
    at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:239) 
    at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:122) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) 
    at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) 
    at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4019) 
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) 
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) 
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) 
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) 
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) 
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) 
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) 
    at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:164) 
    at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2696) 
    at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1075) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1039) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) 
    at com.sun.proxy.$Proxy101.find(Unknown Source) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne(SimpleJpaRepository.java:241) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
    ... 39 more 
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field hello.entity.Job.name to java.lang.Integer 
    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) 
    ... 88 more 



mysql> select * from employee; 
+----+------+ 
| id | name | 
+----+------+ 
| 2 | E1 | 
| 3 | E2 | 
+----+------+ 
2 rows in set 

mysql> select * from employee_nick_names; 
+-------------+------------+ 
| employee_id | nick_names | 
+-------------+------------+ 
|   2 | E1A  | 
|   2 | E1B  | 
+-------------+------------+ 
2 rows in set 

mysql> select * from job; 
+----+------+ 
| id | name | 
+----+------+ 
| 2 | Job1 | 
| 3 | Job2 | 
+----+------+ 
2 rows in set 

mysql> select * from job_tags; 
+----------+---------+ 
| job_name | job_tag | 
+----------+---------+ 
| Job1  | Tag1 | 
| Job1  | Tag2 | 
+----------+---------+ 
2 rows in set 

Job.java

@Entity 
@Data 
@AllArgsConstructor 
@NoArgsConstructor 
public class Job implements Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue 
    private Integer id; 
    private String name; 

    @ElementCollection(fetch=FetchType.EAGER) 
// @ElementCollection(fetch = FetchType.LAZY) 
    @CollectionTable(name = "job_tags", joinColumns = @JoinColumn(name = "job_name", referencedColumnName = "name")) 
    @Column(name = "job_tag") 
    private Set<String> tags = new HashSet<String>(); 
} 

Employee.java

@Entity 
@Data 
@AllArgsConstructor 
@NoArgsConstructor 
public class Employee implements Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue 
    private Integer id; 
    private String name; 

    @ElementCollection(fetch=FetchType.EAGER) 
// @ElementCollection(fetch = FetchType.LAZY) 
    private Set<String> nickNames = new HashSet<String>(); 
} 

JobDao.java

public interface JobDao extends JpaRepository<Job, Integer> {} 

EmployeeDao.java

public interface EmployeeDao extends JpaRepository<Employee, Integer> {} 

ApplocationTest.java

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class ApplicationTests { 

    @Autowired 
    JobDao jobDao; 
    @Autowired 
    EmployeeDao employeeDao; 

    @Test 
    public void testEmployee() { 
     employeeDao.findAll().forEach(e -> employeeDao.delete(e)); 

     Employee e1 = new Employee(); 
     e1.setName("E1"); 
     e1.setNickNames(Sets.newSet("E1A", "E1B")); 
     employeeDao.save(e1); 

     Employee e2 = new Employee(); 
     e2.setName("E2"); 
     employeeDao.save(e2); 
    } 

    @Test 
    @Transactional 
    public void testEmployee2() { 
     Employee employee1 = employeeDao.findOne(2); 
     System.out.println(employee2); 
     Employee employee2 = employeeDao.findOne(3); 
     System.out.println(employee3); 
    } 

    @Test 
    public void testJob() { 
     jobDao.findAll().forEach(e -> jobDao.delete(e)); 

     Job job1 = new Job(); 
     job1.setName("Job1"); 
     job1.setTags(Sets.newSet("Tag1", "Tag2")); 
     jobDao.save(job1); 

     Job job2 = new Job(); 
     job2.setName("Job2"); 
     jobDao.save(job2); 
    } 

    @Test 
    @Transactional 
    public void testJob2() { 
     Job job1 = jobDao.findOne(2); 
     System.out.println(job2); 
     Job job2 = jobDao.findOne(3); 
     System.out.println(job3); 
    } 
} 

回答

0

當您查詢工作

懷着熱切的

Hibernate會立即得到 「job_tags」

,並得到name字段的值,

領域是私人==>訪問被拒絕,你可以嘗試改變領域公共

冬眠獲取作業形式的數據庫(不得到「job_tags」)

job_tags將被加載時,隱式調用的getter getJobTags

+0

變化'private'到'public'不會解決這個問題。這不是關於字段是私人的。根據錯誤信息引發:java.lang.IllegalArgumentException:無法設置java.lang.String字段hello.entity.Job。名稱爲java.lang.Integer''由org.hibernate.property.access.spi.PropertyAccessException導致:通過持久屬性反射訪問字段[public java.lang.String hello.entity.Job.name]時出錯[你好。 entity.Job#name]:3'它總是使用整數job_id從job_tags查詢,但表'job_tags(job_name,job_tag)',我不知道爲什麼 – phxism