私はこれが非常に頻繁に尋ねられることを知っています、しかし私は実用的な解決策を見つけることができません:
これは私のAbstractDAOです:
public interface AbstractDao<T>
{
public T get(Serializable id);
//other CRUD operations
}
そして、これは私のJPAの実装です。
public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T> , Serializable
{
protected EntityManager em;
protected Class<T> clazz;
@SuppressWarnings("unchecked")
public AbstractDaoJpaImpl()
{
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.clazz = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
}
public abstract void setEntityManager(EntityManager em);
//implementations skipped
}
そしてこれは1つのエンティティのdaoです:
public interface PersonDao extends AbstractDao<Person>
{
//empty
}
その実装は次のとおりです。
@Repository
public class PersonDaoImpl extends AbstractDaoJpaImpl<Person> implements PersonDao , OtherInterface
{
@PersistenceContext(unitName="company")
@Override
public void setEntityManager(EntityManager em)
{
this.em = em;
}
@Override // implements OtherInterface.additionalMethods()
public additionalMethods()
{
// implements...
}
}
アーキテクチャ全体は単純です:
インターフェイスAbstractDaoは、単純なCRUDメソッドを定義します。
インターフェイスPersonDaoは、アドオンメソッドなしでAbstractDAOを拡張します。
クラスAbstractDaoJpaImplは、JPAによるAbstractDaoの実装を定義します。
クラスPersonDaoImplは、AbstractDaoJpaImplを拡張し、aditionalMethods ()を追加するPersonDaoANDOtherInterfaceを実装します。
、PersonDaoImplはPersonDaoのみを実装し、OtherInterface.additionalMethods()を実装しない場合、すべてが正常に機能します。
使うことができます
<tx:annotation-driven transaction-manager="transactionManager" />
私の春のXMLファイルで。
しかし、PersonDaoImplはOtherInterfaceを実装します。テスト/実行するとき、DAOをPersonDaoからPersonDaoImplまたはOtherInterfacesにキャストする必要があります。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManager" , defaultRollback=false)
public class PersonDaoTest
{
@Inject
PersonDao dao;
@Test
public void testAdditionalMethod()
{
PersonDaoImpl impl = (PersonDaoImpl) dao;
System.out.println(impl.additionalMethod(...));
}
}
この問題は(PersonDaoImpl) dao
、「プロキシをPersonDaoImplにキャストできません」という例外をスローする場合に発生します。
java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)
これはグーグルするときによく聞かれます、誰もがに追加proxy-target-class="true"
することを提案し<tx:annotation-driven>
ます:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
これにより、JDKの動的プロキシの代わりにCGLIBが使用されます。
しかし、Springを初期化するときに別の例外をスローします:
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
AbstractDaoJpaImplのコンストラクター:
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
すべての質問はここで止まります、私は今、実用的な解決策を見つけることができません。
誰かが私に実用的な解決策を与えることができますか?どうもありがとう !
環境:Spring-3.0.4、javaee-api-6.0、javax.inject、cglib-2.2、hibernate-jpa-2.0-api-1.0.0、