这是我的hbm和测试代码。我正在使用Spring的HibernateTemplate。我不使用DAO。 Hibernate 2.2.5 with Spring 2.0.7
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 :(得分:0)
因为同一个类的实例都是父类和子类,所以你需要一个id,但是你还需要db(和类中的字段)中的parent-id类型列,这样孩子们就可以拥有引用他们的父母。
答案 1 :(得分: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>
答案 2 :(得分:0)
当你建立双向关系时,你需要把inverse = true,否则hibernate将尝试进行双重访问,这就是你得到异常的原因。 Hibernate需要知道关系的哪一方是能够控制保存和更新的人。