Sé que muy a menudo se le pide, pero no puedo encontrar una solución de trabajo:¡Patrón abstracto de DAO y problema de Spring: "El proxy no se puede convertir en ..."!
Ésta es mi AbstractDAO:
public interface AbstractDao<T>
{
public T get(Serializable id);
//other CRUD operations
}
y esto es la aplicación de mi 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
}
Y esto es el dao de una entidad:
public interface PersonDao extends AbstractDao<Person>
{
//empty
}
Aquí es su implementación:
@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...
}
}
toda la arquitectura es simple:
interfaz AbstractDao define métodos CRUD simples.
Interfaz PersonDao extiende AbstractDAO sin ningún método de complemento.
clase AbstractDaoJpaImpl define la implementación de JPA de AbstractDao
clase PersonDaoImpl extiende AbstractDaoJpaImpl e implementa PersonDao Y OtherInterface, que añade aditionalMethods() ...
SI, PersonDaoImpl sólo se implementa PersonDao, sin implementar OtherInterface.additionalMethods(), todo funciona bien.
puedo usar
<tx:annotation-driven transaction-manager="transactionManager" />
en el archivo XML de mi primavera.
PERO, PersonDaoImpl implementa OtherInterface (s), cuando se prueba/marcha, I tiene que emitir el DAO de PersonDao a PersonDaoImpl o OtherInterfaces, tales como:
@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(...));
}
}
El problema se produce cuando (PersonDaoImpl) dao
, que tiros "proxy no se puede convertir a PersonDaoImpl" excepción:
java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)
esto se hace a menudo cuando googleing, todo el mundo sugieren la adición de proxy-target-class="true"
a <tx:annotation-driven>
:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
Esto hará uso de CGLIB en lugar del proxy dinámico de JDK.
PERO tiros otra excepción al inicializar la primavera:
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
en el constructor del AbstractDaoJpaImpl:
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
Cada pregunta se detiene aquí, no puedo encontrar ningún trabajo soluciones ahora.
¿Alguien puede darme una solución de trabajo? ¡Muchas gracias!
Medio Ambiente: Primavera-3.0.4, JavaEE-API-6.0, javax.inject, cglib-2.2, hibernación-APP-2,0-api-1.0.0,
Gracias, debería @Inject OtherInterface otherInterfaceImpl; y prueba contra otherInterfaceImpl. Funciona ! – smallufo