这分别是我的hbm和测试代码。我正在使用Spring的HibernateTemplate。我不使用DAO。使用Spring 2.0.7的Hibernate 2.2.5
血红蛋白
<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
好的,根本原因是我对集合的映射无效。感谢这篇关于复合映射的文章
错误:
<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>