EntityManagerに基づくJPAサブテーブルの追加、削除、変更、およびクエリの実装
この記事では、EclipseLinkのJPA実装を使用しています。関連するJPAアクセスについては、他のブログ投稿を参照してください。
まず、JPAサブテーブルの追加、削除、変更、およびクエリ操作を実装するために何をする必要があるかについて説明しましょう。
- サブテーブルルールの定義(つまり、メインテーブルからサブテーブルへの変換の実現)
- サブテーブル操作の実装(つまり、EntityManagerはサブテーブルルールに従って特定のサブテーブルを操作します)
EntityManager永続化操作
一般的なインターフェイスメソッドは次のとおりです。
// 新增
void persist(Object var1);
// 更新
<T> T merge(T var1);
// 删除
void remove(Object var1);
// 查找
<T> T find(Class<T> var1, Object var2);
上記の追加、削除、変更、およびチェックのインターフェイスメソッドの実装を分析してみましょう。
org.eclipse.persistence.internal.jpa.EntityManagerImpl
-
永続入力
パラメーター:エンティティオブジェクトインスタンス出力
パラメーター:なし
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl
-
マージ入力
パラメーター:エンティティオブジェクトインスタンス
出力パラメーター:エンティティオブジェクトインスタンス
-
入力
パラメータを削除:エンティティオブジェクトインスタンス
出力パラメータ:なし
-
入力
パラメータの検索:エンティティクラスクラス、エンティティクラス主キー
出力パラメータ:エンティティオブジェクトインスタンス
次に、getDescriptorメソッドの特定の実装を理解する必要があります。
org.eclipse.persistence.internal.sessions.AbstractSession
ClassDescriptorは、最終的にlastDescriptorAccessed変数にキャッシュされます。
最後に、デバッグビューに切り替えて、ClassDescriptorを確認します。ここから、実際のテーブル名に関連するDatabaseTableを確認できます。
この時点で、テーブル名がDatabaseTableに格納されていることはすでにわかっています。サブテーブル操作を実装する場合は、ここで値を動的に変更する必要があります。
私たちがしなければならない上記のことに対する解決策を以下に示します。
サブテーブルルールの定義
エンティティクラスで定義されたテーブル名は、メインテーブル名として理解できます。サブテーブル名の命名規則を最初に決定する必要があり、次の構成が定義されています。
<?xml version="1.0" encoding="UTF-8"?>
<tables>
<!-- 定义分表配置
name : 分表对应的主表名
exp : 分表名表达式 (FLEA_TABLE_NAME)_(列名大写)_(列名大写)
-->
<table name="flea_login_log" exp="(FLEA_TABLE_NAME)_(CREATE_DATE)" desc="Flea登录日志表分表规则">
<splits>
<!-- 定义分表后缀
key : 分表类型关键字 (可查看 com.huazie.frame.db.common.table.split.TableSplitEnum )
column : 分表属性列字段名
implClass : 分表后缀转换实现类
-->
<split key="yyyymm" column="create_date" implClass="com.huazie.frame.db.common.table.split.impl.YYYYMMTableSplitImpl"/>
</splits>
</table>
</tables>
テーブル分割ルールに関連する実装コードについては、GitHubに移動してTableSplitHelperを表示できます。
サブテーブル操作の実現
上記のサブテーブルルールの定義では、サブテーブル名式expがメインテーブル名とサブテーブルフィールドで構成されており、サブテーブルフィールドの変換実装ルールがsplitによって定義されていることがわかります。
サブテーブルプロセッサはEclipseLinkTableSplitHandlerを実装します
@Override
public void handle(EntityManager entityManager, Object entity, boolean isRead) throws Exception {
if (ObjectUtils.isEmpty(entityManager) || ObjectUtils.isEmpty(entity)) {
return;
}
// 获取分表信息(包括主表名 和 分表名 【如果存在分表返回】)
SplitTable splitTable = EntityUtils.getSplitTable(entity);
// 存在分表,则需要操作具体分表
if (StringUtils.isNotBlank(splitTable.getSplitTableName())) {
// 获取可用的数据库会话对象
AbstractSession session;
if (isRead) {
session = entityManager.unwrap(AbstractSession.class);
} else {
session = entityManager.unwrap(RepeatableWriteUnitOfWork.class);
}
// 重新设置 查询的分表表名
session.getDescriptor(entity.getClass()).setTableName(splitTable.getSplitTableName());
}
}
JPAサブテーブルの追加、削除、変更、およびチェックに関連するコードは、GitHubにあり、AbstractFleaJPADAOImplおよびEclipseLinkTableSplitHandlerを表示できます。セルフテストクラスの場合は、AuthSpringTestを表示できます。