2017-01-23 10 views
1

MyBatisを使用してDBへの呼び出しをいくつか集計しようとしていますが、これまでのところ壁に衝突しました。インターフェイスの汎用タイプと多相

public interface Entity { 

    <T extends Entity> Class<Insertable<T>> mapper(); 
} 

public interface Insertable<T extends Entity> { 

    void insert(T entity); 
} 

public interface ClientMapper extends Insertable<Client> { 

    void insert(Client client); 
} 

public interface CampaignMapper extends Insertable<Campaign> { 

    void insert(Campaign campaign); 
} 

public class Client implements Entity { 

    private final Long id; 

    public Client(final Long id) { 
     this.id = id; 
    } 

    @Override 
    public <T extends Entity> Class<Insertable<T>> mapper() { 
     return ClientMapper.class; // Incompatible types error 
    } 

私はClientMapperClientEntityのタイプである、タイプInsertable<Client>であるにも関わらず、このコンパイルエラーを取得しています:

のは、私は、エンティティとマッパーこれを持っているとしましょう。

目的は次のタイプセーフなコードになっている:

public class MapperOperation { 

    public static void insert(Entity entity) { 
     insert(entity, entity.mapper()); 
    } 

    private static <V extends Entity, K extends Insertable<V>> void insert(V entity, Class<K> mapperClass) { 
     try (SqlSession session = PersistenceManager.get().openSession()) { 
      K mapper = session.getMapper(mapperClass); 
      mapper.insert(entity); 
      session.commit(); 
     } catch (Exception e) { 
      log.error("Could not insert entity {}", entity, e); 
     } 
    } 
} 

この方法では、私はただのEntityのインスタンスとメソッドinsertを呼び出し、次にように私に彼mapperを与えるために彼を求めることができます私はそれを挿入することができます。

これは可能ですか?私は何か間違っているのですか?

+0

私は「話題から外れている」という疑問を持っています。「ClientMapper」と「CampaignMapper」のインターフェースは何ですか?つまり、同じシグネチャで挿入メソッドを再宣言するだけです。 –

+0

Mybatisの仕組み(私が知る限り)です。各インタフェースには、実行されるクエリに関連付けられたXMLがあります。セッションを使用してそのインターフェース(マッパー)のインスタンスを取得し、メソッドを呼び出すと、Mybatisがその魔法を行います。 – carcaret

答えて

4

それは、これらの変更でコンパイルする必要があります。

public interface Entity { 
    <T extends Entity> Class<? extends Insertable<T>> mapper(); 
}  

// ... 

public <T extends Entity> Class<? extends Insertable<T>> mapper() { 
    return ClientMapper.class; 
} 

あなたはList<Number>List<Integer>を割り当てることはできません同じ理由で、Class<Insertable<T>>Class<ClientMapper>を割り当てることはできません。

あなたは、それが安全ではないだろう可能性がある場合:

List<Integer> li = new ArrayList<>(); 
List<Number> ln = li; // does not compile 
ln.add(3.14); 
Integer i = li.get(0); // it's a Double! 

はEDIT:これが唯一の問題ではありません。この方法は、Tに依存何かを返しますが、あなたは別のものを返します。問題を簡略化することができる:TBに解決される可能性がありますので

ここ
class A {} 
class B extends A {} 
class C extends A {} 

<T extends A> T getValue() { 
    return new C(); 
} 

TAの任意のサブタイプに解決される可能性がありますので、我々はCのインスタンスを返すことができません(this.<B>getValue()を呼び出すことによって)、およびCですサブタイプはBではありません。

+0

それでも、私には同じエラー「互換性のない型:java.lang.Class はjava.lang.Classに変換できません<? extend > ' – carcaret

+0

はい、これは唯一の問題ではありませんでした。私は私の答えを編集しました。 – rom1v

+0

私は問題があると思う。それでは回避策はないと思いますよね?最終的に、私が達成したいのは、 'insert(entity、entity.mapper())'が型安全であるということです。 – carcaret

関連する問題