Абстрактный шаблон DAO и проблема Spring «Прокси не может быть приведен к…»!
Я знаю, что это очень часто спрашивают, но я не могу найти рабочее решение:
Это мой 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
}
И это дао одной сущности:
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 и реализует PersonDaoИ OtherInterface, который добавляет aditionalMethods ()...
ЕСЛИ PersonDaoImpl реализует только PersonDao, без реализации OtherInterface.additionalMethods (), все работает нормально.
я могу использовать
<tx:annotation-driven transaction-manager="transactionManager" />
в XML-файле моей весны.
НО, PersonDaoImpl реализует OtherInterface (s), при тестировании / выполнении янеобходимо привести 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)
это часто спрашивают при поиске в Google, все предлагают добавитьproxy-target-class="true"
в<tx:annotation-driven>
:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
Это будет использовать CGLIB вместо динамического прокси JDK.
НО это вызывает другое исключение при инициализации 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,