私のプロジェクトのすべてのモデルのベースとして使用している次のクラスがあります。
_public abstract class BaseModel
{
static String table;
static String idField = "id";
public static boolean exists(long id) throws Exception
{
Db db = Util.getDb();
Query q = db.query();
q.select( idField ).whereLong(idField, id).limit(1).get(table);
return q.hasResults();
}
//snip..
}
_
それから、次の方法でそれから拡張しようとしています:
_public class User extends BaseModel
{
static String table = "user";
//snip
}
_
ただし、次のことをしようとすると:
_if ( User.exists( 4 ) )
//do something
_
次に、クエリ__"SELECT id FROM user WHERE id = ?"
_ではなく、クエリ "NULLからのidの選択WHERE WHERE =?"を生成します。そのため、table
クラスのUser
フィールドをオーバーライドしても効果はないようです。
どうすればこれを克服できますか? setTable()
メソッドをBaseModelに追加し、User
のコンストラクターでsetTable()
を呼び出すと、table
の新しい値が利用可能になりますUser
クラスのすべてのメソッドも同様ですか?
Javaでは、任意のタイプの静的メソッドまたはフィールドをオーバーライドできません。
public class User extends BaseModel
{
static String table = "user";
//snip
}
これにより、User#table
と同じ名前を持つ新しいフィールドBaseModel#table
が作成されます。ほとんどのIDEはそれについて警告します。
BaseModelのフィールドの値を変更すると、他のすべてのモデルクラスにも適用されます。
1つの方法は、基本メソッドをジェネリックにすることです
protected static boolean exists(String table, long id) throws Exception
{
Db db = Util.getDb();
Query q = db.query();
q.select( idField ).whereLong(idField, id).limit(1).get(table);
return q.hasResults();
}
サブクラスで使用します
public static boolean exists(long id)
{
return exists("user", id);
}
フィールドアプローチを使用する場合は、BaseDAO
クラスを作成し、それに応じてフィールドを設定するUserDAO
(モデルクラスごとに1つ)を作成する必要があります。次に、すべてのdaosのシングルトンインスタンスを作成します。
Javaではstatic
のメンバーをオーバーライドすることはできないため、基本的には少し冗長で全体的に優れた シングルトンパターン に頼る必要があります。概念的には「静的」コードを記述していますが、技術的には(global/singleton /「static」)インスタンスを使用しているため、static
の制限による制限を受けません。
(フィールドはポリモーフィズムに関与しないため、オーバーライドできないため、メソッドを使用する必要があることに注意してください)
public abstract class BaseTable {
public abstract String table();
public String idField() { return "id"; }
public boolean exists(long id) {
// don't build queries this way in real life though!
System.out.println("SELECT count(*) FROM " + table() + " WHERE " + idField() + " = " + id);
return true;
}
}
public class UserTable extends BaseTable {
public static final User INSTANCE = new UserTable();
private UseTabler() {}
@Override public String table() { return "user"; }
}
public class PostTable extends BaseTable {
public static final Post INSTANCE = new PostTable();
private PostTable() {}
@Override public String table() { return "post"; }
}
public static void main(String[] args) {
UserTable.INSTANCE.exists(123);
PostTable.INSTANCE.exists(456);
}
出力:
SELECT count(*) FROM user WHERE id = 123
SELECT count(*) FROM post WHERE id = 456
目的の処理を実行するために、table
でBaseModel
を静的にしないでください。次に、BaseModel
を継承する他のクラスで、デフォルトコンストラクターのtable
を任意の値に設定できます。
static {
table = "user";
}