2011-02-24 66 views
1

這是我的hbm和測試代碼。我正在使用Spring的HibernateTemplate。我不使用DAO。 Hibernate的2.2.5與2.0.7春季Hibernate級聯保存時異常=「save-update」

HBM

<class name="Product" table="PRODUCT"> 
     <id name="id" type="java.lang.Long" column="ID"> 
      <generator class="native"> 
       <param name="sequence">PRODUCT_SN</param> 
      </generator> 
     </id> 

     <set name="children" lazy="false" table="PRODUCT" cascade="save-update"> 
      <key> 
       <column name="ID" /> 
      </key> 
      <one-to-many class="Product" /> 
     </set> 
     <property name="code" type="java.lang.String" column="CODE" not-null="true" /> 
     <property name="name" type="java.lang.String" column="NAME" /> 
     <property name="startDate" type="java.util.Date" column="STARTDATE" /> 
     <property name="endDate" type="java.util.Date" column="ENDDATE" /> 
     <property name="decisionable" type="boolean" column="ISDECISIONABLE" /> 
     <property name="selectable" type="boolean" column="ISSELECTABLE" /> 
    </class> 

測試

public class ProductTest extends HibernateTestCase 
{ 
    @Test 
    public void save() 
    { 
     // Level 1 - mortgage LOB 
     Product mortgage = new Product(); 
     mortgage.setCode("Mortgage"); 

     Product ml = new Product(); 
     ml.setCode("Mortgage Loan"); 

     Product me = new Product(); 
     me.setCode("Home Equity LOC"); 

     mortgage.addChild(ml); 
     // mortgage.addChild(me); 

     hibernateTemplate.save(mortgage); 
    } 

    @Override 
    public List<String> getHbmResourceUnderTest() 
    { 
     return Lists.newArrayList("Product.hbm.xml"); 
    } 
} 

超級測試類

public abstract class HibernateTestCase 
{ 
    protected HibernateTemplate hibernateTemplate; 

    protected TransactionTemplate transTemplate; 

    public TransactionTemplate getTransTemplate() 
    { 
     return transTemplate; 
    } 

    protected PlatformTransactionManager transactionManager; 

    @Before 
    public void setUp() throws Exception 
    { 
     Configuration configuration = new Configuration(); 
     configuration.setProperty(Environment.DRIVER, "org.hsqldb.jdbcDriver"); 
     configuration.setProperty(Environment.URL, "jdbc:hsqldb:mem:test"); 
     configuration.setProperty(Environment.USER, "sa"); 
     configuration.setProperty(Environment.DIALECT, HSQLDialect.class.getName()); 
     configuration.setProperty(Environment.SHOW_SQL, "true"); 
     configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop"); 
     configuration.setProperty(Environment.STATEMENT_BATCH_SIZE, "5"); 

     for (String resource : getHbmResourceUnderTest()) 
     { 
      configuration.addResource(resource); 
     } 
     SessionFactory sessionFactory = configuration.buildSessionFactory(); 

     transactionManager = new HibernateTransactionManager(sessionFactory); 
     hibernateTemplate = new HibernateTemplate(sessionFactory); 
     transTemplate = new TransactionTemplate(transactionManager); 
    } 

    public abstract List<String> getHbmResourceUnderTest(); 
} 

錯誤

insert into PRODUCT (ID, CODE, NAME, STARTDATE, ENDDATE, ISDECISIONABLE, ISSELECTABLE) values (null, ?, ?, ?, ?, ?, ?) 
binding 'Mortgage' to parameter: 1 
binding null to parameter: 2 
binding null to parameter: 3 
binding null to parameter: 4 
binding 'false' to parameter: 5 
binding 'false' to parameter: 6 
Hibernate: call identity() 
insert into PRODUCT (ID, CODE, NAME, STARTDATE, ENDDATE, ISDECISIONABLE, ISSELECTABLE) values (null, ?, ?, ?, ?, ?, ?) 
binding 'Mortgage Loan' to parameter: 1 
binding null to parameter: 2 
binding null to parameter: 3 
binding null to parameter: 4 
binding 'false' to parameter: 5 
binding 'false' to parameter: 6 
Hibernate: call identity() 
update PRODUCT set ID=? where ID=? 
binding '1' to parameter: 1 
binding '2' to parameter: 2 
SQL Error: 0, SQLState: null 

ERROR [org.hibernate.util.JDBCExceptionReporter] failed batch 
ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session 
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update 
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103) 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:145) 
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298) 
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) 
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) 
    at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390) 
    at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373) 
    at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:632) 
    at com.equifax.ic.platform.domain.product.ProductTest.save(ProductTest.java:28) 
    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:49) 
    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: java.sql.BatchUpdateException: failed batch 
    at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source) 
    at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source) 
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246) 
    ... 32 more 

回答

0

好的根本原因是我的一部分用於集合無效的映射。由於這個article on composite mapping

錯誤:

<key> 
    <column name="ID" /> 
</key> 

正確

<many-to-one name="parent" class="Product" lazy="false" column="PARENT" /> 

<set name="children" lazy="false" fetch="join" table="PRODUCT" cascade="all"> 
    <key> 
    <column name="PARENT" /> 
    </key> 
    <one-to-many class="Product" /> 
</set> 

完全映射

<class name="Product" table="PRODUCT"> 
     <id name="id" type="java.lang.Long" column="ID"> 
      <generator class="native"> 
       <param name="sequence">PRODUCT_SN</param> 
      </generator> 
     </id> 

     <many-to-one name="parent" class="Product" lazy="false" column="PARENT" /> 

     <set name="children" lazy="false" fetch="join" table="PRODUCT" cascade="all"> 
      <key> 
       <column name="PARENT" /> 
      </key> 
      <one-to-many class="Product" /> 
     </set> 
     <property name="code" type="java.lang.String" column="CODE" not-null="true" /> 
     <property name="name" type="java.lang.String" column="NAME" /> 
     <property name="startDate" type="java.util.Date" column="STARTDATE" /> 
     <property name="endDate" type="java.util.Date" column="ENDDATE" /> 
     <property name="decisionable" type="boolean" column="ISDECISIONABLE" /> 
     <property name="selectable" type="boolean" column="ISSELECTABLE" /> 
    </class> 
0

,因爲同一個類的實例是父母和孩子,你需要一個id,你有,但你也需要在一個數據庫中的父ID類型列(和現場類),所以孩子們可以參考他們的父母。

https://forum.hibernate.org/viewtopic.php?f=1&t=1004163

+0

@hggotcodes這是工作沒有父母,當我設置inverse =「true」......任何想法爲什麼? –

+0

也加入這給我同樣的錯誤:<多對一的名稱=「父母」class =「產品」lazy =「false」列=「PARENTID」/>。只有加入inverse =「true」纔有效;-( –

0

當你做你需要把逆雙向關係=真,否則冬眠是將嘗試做雙重訪問,這就是爲什麼你會得到一個例外。 Hibernate需要知道關係的哪一方是保存和更新的控制者。