2017-05-29 194 views
0

我最近添加JpaTransactionManager到我的配置和嘗試使用Spring交易。它似乎工作正常,除了我在下面添加的一個測試。JPA /休眠與春季交易不提交

爲什麼我沒有得到預期的IllegalStateException?我預計這會失敗,因爲parentCategory字段中的CascadeType設置爲NONE。 如果我在庫類中添加em.flush();,我確實得到了預期的異常。

據我所知,在我的測試中添加@Transaction只添加了begin,commit和rollback事務方法。所以它應該在提交方法失敗,但它沒有。

根據Hibernate User Guidehibernate.transaction.flush_before_completion默認爲false。這是我沒有得到預期的異常的原因嗎?

有一個similair post用戶指出提交將導致刷新。這也是我決定問這個問題的原因。


這是我的實體

@Entity 
@Table(name = "category") 
public class Category { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "category_id", nullable = false, insertable = false, updatable = false) 
    private Long id; 

    @Column(name = "category", nullable = false, unique = true) 
    private String categoryName; 

    @ManyToOne // Default is CascadeType.NONE 
    @JoinColumn(name = "parent_category_id", referencedColumnName = "category_id") 
    private Category parentCategory; 

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parentCategory") 
    private List<Category> childCategories = new ArrayList<>(); 

    public Category(String categoryName, Category parentCategory) { 
    this.categoryName = categoryName; 
    this.parentCategory = parentCategory; 
    } 

    // default constructor, getters and setters ... 
} 

這是我的倉庫

@Repository 
public class CategoryDaoImpl { 

    @PersistenceContext protected EntityManager em; 

    @Override 
    public E persist(E entity) { 
    em.persist(entity); 
    // em.flush(); // Why doesnt Spring transactions automatically add the em.flush() inside the transaction? 
    return entity; 
    } 

} 

這是我的測試

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = DbConfig.class) 
@Transactional 
public class CategoryDaoTest { 

    @Autowired private CategoryDao categoryDao; 

    @Test(expected = IllegalStateException.class) 
    public void createTwoCategoriesPersistChildAndGetIllegalStateException() { 
    Category childCategory = new Category("firstChild", new Category("rootCategory", null)); 

    categoryDao.persist(childCategory); 
    } 

} 

這是我的配置

@Configuration 
@ComponentScan(basePackages = "nl.yoshuan.pricecomparer") 
@EnableTransactionManagement 
public class TestConfig { 

    @Bean 
    public DataSource dataSource() { 
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 
    return builder.setType(EmbeddedDatabaseType.HSQL).build(); 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
    factory.setJpaVendorAdapter(vendorAdapter); 
    factory.setPackagesToScan("nl.yoshuan.pricecomparer.entities"); 
    factory.setDataSource(dataSource()); 

    Map<String, Object> jpaProperties = new HashMap<>(); 
    jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); 
    jpaProperties.put("hibernate.show_sql", true); 
    jpaProperties.put("hibernate.format_sql", true); 
    jpaProperties.put("hibernate.use_sql_comments", true); 
    jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop"); 
    factory.setJpaPropertyMap(jpaProperties); 

    return factory; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
    JpaTransactionManager txManager = new JpaTransactionManager(); 
    txManager.setEntityManagerFactory(entityManagerFactory().getObject()); 
    return txManager; 
    } 

} 

這是我的控制檯輸出

2017-05-29 15:43:14 INFO TransactionContext:101 - Began transaction (1) for test context [[email protected] testClass = CategoryDaoUTest, testInstance = [email protected], testMethod = [email protected]DaoUTest, testException = [null], mergedContextConfiguration = [[email protected] testClass = CategoryDaoUTest, locations = '{}', classes = '{class nl.yoshuan.pricecomparer.config.TestConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [[email protected]]; rollback [true] 
Hibernate: 
    /* insert nl.yoshuan.pricecomparer.entities.Category 
     */ insert 
     into 
      category 
      (category_id, category, parent_category_id) 
     values 
      (default, ?, ?) 
2017-05-29 15:43:14 INFO TransactionContext:136 - Rolled back transaction for test context [[email protected] testClass = CategoryDaoUTest, testInstance = [email protected], testMethod = [email protected]DaoUTest, testException = java.lang.AssertionError: Expected exception: java.lang.IllegalStateException, mergedContextConfiguration = [[email protected] testClass = CategoryDaoUTest, locations = '{}', classes = '{class nl.yoshuan.pricecomparer.config.TestConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]. 
2017-05-29 15:43:14 INFO GenericApplicationContext:987 - Closing [email protected]206065: startup date [Mon May 29 15:43:14 CEST 2017]; root of context hierarchy 
2017-05-29 15:43:14 INFO LocalContainerEntityManagerFactoryBean:548 - Closing JPA EntityManagerFactory for persistence unit 'default' 
2017-05-29 15:43:14 INFO SchemaDropperImpl$DelayedDropActionImpl:524 - HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down' 
Hibernate: 

    alter table category 
     drop constraint FKs2ride9gvilxy2tcuv7witnxc 
Hibernate: 

    drop table category if exists 
2017-05-29 15:43:14 INFO EmbeddedDatabaseFactory:217 - Shutting down embedded database: url='jdbc:hsqldb:mem:testdb' 

java.lang.AssertionError: Expected exception: java.lang.IllegalStateException 

    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:32) 
    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.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 
+0

更新的控制檯輸出。 –

回答

0

我想你應該添加@TransactionConfiguration到你的單元測試。 TransactionConfiguration定義了用於配置事務測試的類級元數據。

+0

'@ TransactionConfiguration'已被棄用,而不是我正在尋找的。 '@ Rollback'也不是。 '@ Commit'確實可行,但現在發生異常現象發生在我的方法之後。我得到了'java.lang.AssertionError:期望的異常:java.lang.IllegalStateException',之後,我得到了我的InvalidDataAccessApiUsageException - > TransientPropertyValueException - > IllegalStateException stacktrace –