對象模型:父實體 Address 持有 Set<Phone> phones,子實體 Phone 可選擇持有反向引用。
Hibernate 單向映射:外鍵在子表,不映射到子對象屬性,外鍵列必須可空(先插入子行再更新)。
Hibernate 雙向映射:子對象有外鍵屬性,列可非空,但引入循環依賴與雙向維護成本。
OpenJPA 關鍵差異:不支援單向一對多外鍵映射,必須使用連接表。建議將單向轉為雙向(添加反向屬性),修改代碼雙向維護關系,避免變更數據庫結構。
<!-- OpenJPA 雙向一對多 XML 映射 -->
<entity class="Address">
<one-to-many name="phones" mapped-by="address">
<cascade><cascade-all/></cascade>
</one-to-many>
</entity>
<entity class="Phone">
<many-to-one name="address">
<join-column name="ADDR_TID"/>
</many-to-one>
</entity>
特殊功能遷移:
inverse="true" → OpenJPA 非擁有端(無外鍵端)cascade="all-delete-orphan" → JPA 無標準對應,OpenJPA 提供專有 @ElementDependent;標準遷移需代碼顯式 remove() 子對象cascade=CascadeType.ALL,否則 merge() 會失敗(OpenJPA 0.9.7 已知問題)映射表由擁有端持有。Hibernate 使用 inverse="true" 標識非擁有端;OpenJPA 使用 mapped-by 引用擁有端屬性名。
<!-- OpenJPA 多對多 XML 映射 -->
<entity class="User"> <!-- 擁有端 -->
<many-to-many name="groups">
<join-table name="T_USER_GROUP">
<join-column name="USER_TID"/>
<inverse-join-column name="GROUP_TID"/>
</join-table>
</many-to-many>
</entity>
<entity class="Group"> <!-- 非擁有端 -->
<many-to-many name="users" mapped-by="groups"/>
</entity>
兩者默認均為 LAZY。禁用延遲(啟用 EAGER):
lazy="false",類 lazy="false"fetch="EAGER"分離對象訪問差異:Hibernate 拋出異常,OpenJPA 返回空集合。JPA 規範未規定行為,不可依賴。建議方案:
最佳實踐:系統生成整數鍵(人工鍵),映射為 Long。Hibernate 使用 sequence 生成器;OpenJPA 使用 @SequenceGenerator + @GeneratedValue(strategy=SEQUENCE)。外鍵均基於 OID,帶 ON DELETE RESTRICT 約束。
版本欄位映射基本一致:Hibernate <version>,OpenJPA <version> + @Version。
JPA 僅標準化樂觀鎖。遷移使用悲觀鎖的應用,需在 persistence.xml 配置 OpenJPA 擴展屬性:
<property name="openjpa.LockManager" value="pessimistic"/>
<property name="openjpa.ReadLockLevel" value="read"/>
<property name="openjpa.WriteLockLevel" value="write"/>
<property name="openjpa.jdbc.TransactionIsolation" value="repeatable-read"/>
或編程方式通過 FetchPlan.setReadLockMode(LockModeType.WRITE) 控制單事務鎖定級別。
| 類別 | Hibernate | OpenJPA |
|---|---|---|
| 數據庫方言 | hibernate.dialect | openjpa.jdbc.DBDictionary (可選) |
| 驅動類 | connection.driver_class | openjpa.ConnectionDriverName |
| 連接 URL | connection.url | openjpa.ConnectionURL |
| 用戶名 | connection.username | openjpa.ConnectionUserName |
| 密碼 | connection.password | openjpa.ConnectionPassword |
| 映射文件 | <mapping resource="..."/> | <mapping-file>META-INF/orm.xml</mapping-file> |
| 顯示 SQL | show_sql=true | openjpa.Log=SQL=TRACE + ConnectionFactoryProperties=PrettyPrint=true |
建議:先遷移核心配置,再通過負載測試引入優化參數。