2016-08-29 7 views
0

各テーブルにnamespaceフィールドがあるマルチテナントアーキテクチャを作成しようとしています。どのメソッドが実行されている場合でも、ThreadLocalストレージは現在のnamespaceにアクセスできます。私が望むのは、ビジネスレイヤーがネームスペースの概念に完全に無関心であることです。一例を与えるために:Hibernate/JPA/Spring-Dataで非表示のカラムセッター/ゲッター

CREATE TABLE users(
    first_name CHARACTER VARYING, 
    last_name CHARACTER VARYING, 
    namespace CHARACTER VARYING NOT NULL 
    ... 
); 

私は簡潔にするために主キーと他のフィールドをスキップしています:

@Entity 
@Table(name = "users") 
class Users { 
    @Column(name = "first_name") 
    private String firstName; 

    @Column(name = "last_name") 
    private String lastName; 

    ... 
} 

テーブルusersは、以下のように定義されます。 SELECT * FROM users WHERE (condition)のクエリは、本質的にSELECT * FROM users WHERE (condition & namespace = :1)であるか、またはspring-dataの意味で、findUsersByName(String name)findUsersByNameAndNamespace(String name, String namespace)である必要があります。また、saveの操作では、モデルに名前空間を設定する必要があります。

ただし、モデル定義に名前空間を含めたくありません。これは両面問題です。

  1. すべてfetchには、クエリに名前空間が設定されている必要があります。
  2. すべてsaveは、モデル内の名前空間を保存する必要があります。

ながら、私は最初の問題を解決するためにどのように絶対に見当もつかない、第二の問題は、(部分的に)、その後のHibernateインターセプタを使用して設定されているnamespaceプロパティを持つ親クラスTenantedModelを使用することによって解決することができます。その問題は、ビジネス層がまだnamespace属性を参照できることです。

SpringデータでJPAを使用してこれを行うには、きれいな方法がありますか?

答えて

1

インターセプタを使用して、休止状態によって生成されたSQLを変更できます。

public String onPrepareStatement(String sql) { 
    String newSQLWithNamespace = sql+" and (namespace = "+ nameSpaceValue+")"; 
    return super.onPrepareStatement(newSQLWithNamespace); 
} 

Add a column to all MySQL Select Queries in a single shot

インターセプタは、スレッドのローカル名前空間値を読み取り、SQLを変更できます。

関連する問題