在使用 Hibernate 操作 SQL Server 2000 時,若實體之間存在雙向一對多關係(如 TransOrder 与 OrderItem),並在同一事務中級聯保存父子對象,可能會拋出如下異常:
[Microsoft][SQLServer 2000 Driver for JDBC]Can't start a cloned connection while in manual transaction mode.
此問題源於 Microsoft JDBC 驅動程式的預設行為。當連接處於手動事務模式(AutoCommit=false)且使用 SelectMethod=direct(預設值)時,驅動不允許在同一連接上並發執行多個 Statement。Hibernate 在級聯保存時會產生多條 SQL 語句,導致衝突。
將 JDBC 連接 URL 中的 SelectMethod 屬性設為 cursor,即可允許在手動事務中複用連接執行多條語句。
<property name="hibernate.connection.url">
jdbc:microsoft:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=yourdb
</property>
注意: 建議同時修改 hibernate.cfg.xml 和 Hibernate Synchronizer 產生的 .hibernateSynchronizer 文件,確保所有環境一致。
<!-- TransOrder.hbm.xml -->
<set name="orderItems" table="orderitem" lazy="false" inverse="true" cascade="all">
<key column="Order_ID" />
<one-to-many class="com.kaoyanhelper.dao.OrderItem" />
</set>
<!-- OrderItem.hbm.xml -->
<class name="OrderItem" table="OrderItem">
<id name="id" column="OrderItem_ID" type="java.lang.Integer">
<generator class="identity" />
</id>
<many-to-one name="transOrder" class="com.xx.dao.TransOrder" column="Order_ID" />
</class>
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
TransOrder order = new TransOrder();
order.setAcceptType("www");
order.setAddress("tom");
order.setCity("changzhou");
OrderItem item = new OrderItem();
item.setItemCount(100);
item.setItemMoney("1200.2");
item.setItemType("kysj");
item.setPaperitemId(101);
item.setResourceitemId(102);
order.getOrderItems().add(item);
item.setTransOrder(order); // 維護雙向關係
session.save(order);
tx.commit();
HibernateUtil.closeSession();
應用上述配置後,即可順利完成父子對象的級聯持久化。