2013-07-26 28 views
5

tôi đang sử dụng H2 trong cơ sở dữ liệu bộ nhớ cho thử nghiệm và cấu hình của tôi là như sau:org.hibernate.PersistentObjectException: tách rời thực thể thông qua để tồn tại với H2 trong cơ sở dữ liệu bộ nhớ

1- SpringTestingConfig:

@Configuration 
@ComponentScan(basePackages = "com.myapp.data", excludeFilters = { @Filter(Configuration.class) }) 
@PropertySource("classpath:/test.properties") 
@Profile("test") 
public class SpringTestingConfig { 
    @Bean 
    public DataSource dataSource() { 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setDriverClassName("org.h2.Driver"); 
     dataSource.setUrl("jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS MYAPP"); 
     dataSource.setUsername("sa"); 
     dataSource.setPassword(""); 
     return dataSource; 
    } 
} 

2- MyTestClass:

@RunWith(SpringJUnit4ClassRunner.class) 
@TestExecutionListeners({ WebContextTestExecutionListener.class, 
     DependencyInjectionTestExecutionListener.class, 
     DirtiesContextTestExecutionListener.class, 
     TransactionalTestExecutionListener.class }) 
@ActiveProfiles("test") 
@DirtiesContext 
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { 
     SpringConfig.class, SpringTestingConfig.class, 
     SpringLocalContainerJPAConfig.class, CustomConfiguration.class }) 
@PrepareForTest({ FacesContext.class }) 
@PowerMockIgnore({ "javax.management.*", "javax.xml.parsers.*", 
    "com.sun.org.apache.xerces.internal.jaxp.*", "ch.qos.logback.*", 
    "org.slf4j.*" }) 
public class MyTestClass{ 

    private Company company; 
    private User user; 


    @Test 
    public void signup(){ 

     User user = new User(); 
    Company company = new Company(); 
    company.setName("Test"); 
    company = usService.saveCompany(company); 
    user.setFirstName("Test"); 
    user.setLastName("User"); 
    user.setEmail("[email protected]"); 
    user.setPassword("verySecret"); 
    user.setCompany(company); 
    user = usService.saveUser(user); // gives exception 

    } 

} 

3 Lưu phương pháp:

@Transactional(propagation = Propagation.REQUIRED) 
    public User saveUser(User user) { 
     return userRepository.saveAndFlush(user); //JpaRepository 
    } 

@Transactional(propagation = Propagation.REQUIRED) 
    public Company saveCompany(Company company) { 
     return companyRepository.saveAndFlush(company); //JpaRepository 
    } 

4- JPA Config

@Configuration 
@EnableSpringConfigured 
public class SpringJNDIJPAConfig { 
protected static final Logger logger = LoggerFactory.getLogger(SpringConfig.class); 
protected static final String HIBERNATE_TRANSACTION_JTA_PLATFORM = "hibernate.transaction.jta.platform"; 

@Value("${hibernate.naming_strategy:org.hibernate.cfg.DefaultNamingStrategy}") 
private String namingStrategy; 

@Value("${hibernate.packages_to_scan:com.myapp.data.domain}") 
private String packagesToScan; 

@Value("${spring_config.project_name}") 
private String projectName; 

@Value("${hibernate.show_sql:false}") 
private String showSql; 

@Value("${hibernate.hbm2ddl.auto:update}") 
private String hbm2ddlAuto; 

@Value("${hibernate.format_sql:false}") 
private String formatSql; 

@Value("${hibernate.dialect:org.hibernate.dialect.MySQL5InnoDBDialect}") 
private String hibernateDialect; 

@Value("${hibernate.connection.useUnicode:true}") 
private String useUnicode; 

@Value("${hibernate.connection.characterEncoding:UTF-8}") 
private String characterEncoding; 

@Value("${hibernate.charSet:UTF-8}") 
private String charSet; 

@Value("${hibernate.default_schema}") 
private String defaultSchema; 

@Value("${hibernate.use_default_schema:true}") 
private boolean useDefaultSchema; 

@Value("${hibernate.use_sql_comments:true}") 
private String useSqlComments; 

@Autowired 
private ApplicationContext applicationContext; 

@Autowired 
private DataSource dataSource; 

@Bean 
public HibernateExceptionTranslator hibernateExceptionTranslator() { 
    return new HibernateExceptionTranslator(); 
} 

@Bean 
protected EntityManagerFactory entityManagerFactory() { 
    LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean(); 

    JtaPersistenceUnitManager puManager = new JtaPersistenceUnitManager(); 
    Map<String, DataSource> dataSources = new HashMap<String, DataSource>(); 
    dataSources.put("dataSource", dataSource); 
    puManager.setDataSourceLookup(new MapDataSourceLookup(dataSources)); 
    puManager.setDefaultDataSource(dataSource); 
    puManager.setPackagesToScan(packagesToScan()); 
    bean.setPersistenceUnitManager(puManager); 

    bean.setPersistenceProviderClass(HibernatePersistence.class); 
    bean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 

    Properties jpaProperties = getHibernateProperties(); 
    jpaProperties.put(HIBERNATE_TRANSACTION_JTA_PLATFORM, SpringJtaPlatform.class.getName().toString()); 
    bean.setJpaProperties(jpaProperties); 

    puManager.afterPropertiesSet(); 
    bean.afterPropertiesSet(); 
    return bean.getObject(); 
} 

protected String getDefaultSchema() { 
    String ds = ConfigurationUtil.config().getString("db.schema.name"); 
    if (ds != null) defaultSchema = ds; 
    return defaultSchema; 
} 

protected String getUseUnicode() { 
     return useUnicode; 
} 

protected String getCharacterEncoding() { 
     return characterEncoding; 
} 

protected String getCharSet() { 
     return charSet; 
} 

protected String getFormatSql() { 
    return formatSql; 
} 

protected String getHbm2ddlAuto() { 
    return hbm2ddlAuto; 
} 

protected String getHibernateDialect() { 
    return hibernateDialect; 
} 

protected Properties getHibernateProperties() { 
    Properties properties = new Properties(); 
    properties.put("hibernate.dialect", getHibernateDialect()); 
    properties.put("hibernate.hbm2ddl.auto", getHbm2ddlAuto()); 
    properties.put("hibernate.show_sql", getShowSql()); 
    properties.put("hibernate.use_sql_comments", getUseSqlComments()); 
    properties.put("hibernate.format_sql", getFormatSql()); 
    if(useDefaultSchema) { 
    properties.put("hibernate.default_schema", getDefaultSchema()); 
    } 
    //properties.put("hibernate.ejb.naming_strategy", namingStrategy); 
    properties.put("hibernate.hbm2ddl.import_files", "/import.sql"); 
    //properties.put("hibernate.connection.characterEncoding", getCharacterEncoding()); 
    //properties.put("hibernate.connection.charSet", getCharSet()); 
    //properties.put("hibernate.connection.useUnicode", getUseUnicode()); 
    if(logger.isInfoEnabled()) { 
    logger.info(MessageFormat.format("SET HIBERNATE PROPERTIES: {0}", properties.toString())); 
    } 
    return properties; 
} 

protected String getProjectName() { 
    return projectName; 
} 

protected String getShowSql() { 
    return showSql; 
} 

protected String getUseSqlComments() { 
    return useSqlComments; 
} 

protected String packagesToScan() { 
     return packagesToScan; 
    } 

@Bean 
protected JtaTransactionManager transactionManager() { 
    SpringBeanFactory.setApplicationContext(applicationContext); 
    JtaTransactionManager manager = new JtaTransactionManager(); 
    manager.setTransactionManagerName("java:jboss/TransactionManager"); 
    manager.setUserTransactionName("java:jboss/UserTransaction"); 
    manager.afterPropertiesSet(); 
    return manager; 
} 

} 

5- tài Entity:

@Entity 
@Table(name = "User", uniqueConstraints = { @UniqueConstraint(columnNames = { 
     "CompanyGID", "MPath" }) }) 
public class User extends PersistableEntity implements UserDetails { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = -6520416613985790209L; 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "CompanyGID") 
    private Company company; 

CẤP: mã trong phương pháp thử nghiệm hoạt động rất tốt khi chạy ứng dụng (l cơ sở dữ liệu ocal) trên Jboss và cách gọi mã từ ủng hộ phương pháp đậu, nhưng khi chạy nó từ kiểm tra (trong cơ sở dữ liệu bộ nhớ) nó tiết kiệm công ty và khi cố gắng tiết kiệm sử dụng nó mang lại cho các ngoại lệ:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.myapp.data.domain.Company; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.myapp.data.domain.Company 
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:668) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:106) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at com.myapp.service.UserService.saveUser_aroundBody6(UserService.java:98) 
    at com.myapp.service.UserService$AjcClosure7.run(UserService.java:1) 
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59) 
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63) 
    at com.myapp.service.UserService.saveUser(UserService.java:93) 
    at com.myapp.service.UserService$$FastClassByCGLIB$$697e2a1b.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) 
    at com.myapp.service.UserService$$EnhancerByCGLIB$$abc2864a.saveUser(<generated>) 
    at test.myapp.web.controllers.SignUpBeanTest.testSignUp(SignUpBeanTest.java:126) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    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.PersistentObjectException: detached entity passed to persist: com.myapp.data.domain.Company 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141) 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:842) 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:835) 
    at org.hibernate.ejb.engine.spi.EJB3CascadingAction$1.cascade(EJB3CascadingAction.java:53) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:387) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:330) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:424) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78) 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:852) 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:826) 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:830) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:875) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:354) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush(SimpleJpaRepository.java:368) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    ... 38 more 
+0

một số mã là mất tích trong bài kiểm tra của bạn. Công ty là gì? – ben75

Trả lời

10

Tôi nghĩ vấn đề ở đây:

@Test 
    public void signup(){ 

    User user = new User(); 
    Company company = new Company(); 
    company.setName("Test"); 
    company = usService.saveCompany(company); //object is saved and transaction is closed, so company is detached here. 
    user.setFirstName("Test"); 
    user.setLastName("User"); 
    user.setEmail("[email protected]"); 
    user.setPassword("verySecret"); 
    user.setCompany(company); //u are setting this detached object to user, NOTE user object's company attr is cascade.all which means this company will be saved as well when you save user. 
    user = usService.saveUser(user); // gives exception, because you are saving new user object with detached company object. 

    } 

Vậy làm cách nào để giải quyết? Bạn có thể cho phép người dùng lưu đối tượng công ty, do đó bạn không tiết kiệm công ty một cách rõ ràng, vì cascade.all là trên cho đối tượng công ty trong sử dụng, công ty nên được lưu lại dưới dạng tốt khi sử dụng đang được lưu:

@Test 
    public void signup(){ 

    User user = new User(); 
    Company company = new Company(); 
    company.setName("Test"); 
    user.setFirstName("Test"); 
    user.setLastName("User"); 
    user.setEmail("[email protected]"); 
    user.setPassword("verySecret"); 
    user.setCompany(company); 
    user = usService.saveUser(user); // gives exception 

    } 
+0

ok tôi sẽ thử điều đó, nhưng điều kỳ lạ là chính xác các bước này tôi đã đăng hoạt động rất tốt mà không gặp vấn đề gì trong chế độ phát triển (khi tôi chạy ứng dụng trên jboss và gọi phương thức) nhưng chỉ đưa ra ngoại lệ trong thử nghiệm, ý tưởng? –

+1

bạn là chính xác, đã giải quyết được vấn đề, nhưng điều làm tôi ngạc nhiên là mã không hoạt động tốt trong phương thức hành động bean được quản lý và chỉ thất bại trong kiểm tra !!!!!!!!!!! 1 –

+0

nếu 'công khai đăng ký void() 'được đánh dấu là giao dịch, nó sẽ không thất bại. đó có thể là trường hợp. – Elbek

Các vấn đề liên quan