Tôi biết điều này là rất thường được hỏi, nhưng tôi không thể tìm thấy một giải pháp làm việc:Mẫu DAO trừu tượng và sự cố "Proxy không thể được truyền tới ..." của Spring!
Đây là AbstractDAO tôi:
public interface AbstractDao<T>
{
public T get(Serializable id);
//other CRUD operations
}
Và đây là thực hiện JPA của tôi:
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
}
Và đây là dao của một thực thể:
public interface PersonDao extends AbstractDao<Person>
{
//empty
}
Đây là thực hiện 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...
}
}
Toàn bộ kiến trúc rất đơn giản:
Interface AbstractDao xác định phương pháp CRUD đơn giản.
Giao diện PersonDao mở rộng AbstractDAO mà không có bất kỳ phương pháp bổ trợ nào.
lớp AbstractDaoJpaImpl xác định thực hiện JPA của AbstractDao
lớp PersonDaoImpl kéo dài AbstractDaoJpaImpl và thực hiện PersonDao VÀ OtherInterface, mà thêm aditionalMethods() ...
NẾU, PersonDaoImpl chỉ thực hiện PersonDao, mà không thực hiện OtherInterface.additionalMethods(), mọi thứ đều hoạt động tốt.
tôi có thể sử dụng
<tx:annotation-driven transaction-manager="transactionManager" />
trong tập tin XML mùa xuân của tôi.
NHƯNG, PersonDaoImpl thực hiện OtherInterface (s), khi kiểm tra/chạy, tôi phải cast DAO từ PersonDao để PersonDaoImpl hoặc OtherInterfaces, chẳng hạn như:
@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(...));
}
}
Vấn đề xảy ra khi (PersonDaoImpl) dao
, mà throws "Proxy không thể được đúc để PersonDaoImpl" ngoại lệ:
java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl
at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36)
này thường hỏi khi googleing, mọi người đề nghị thêm proxy-target-class="true"
-<tx:annotation-driven>
:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
Điều này sẽ sử dụng CGLIB thay vì proxy động của JDK.
NHƯNG nó ném một ngoại lệ khi khởi tạo mùa xuân:
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
trong constructor AbstractDaoJpaImpl của:
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
Mỗi câu hỏi dừng lại ở đây, tôi không thể tìm thấy bất kỳ làm việc giải pháp bây giờ.
Có ai cho tôi giải pháp làm việc không? Cảm ơn rất nhiều!
Môi trường: Mùa xuân-3.0.4, JavaEE-api-6.0, javax.inject, cglib-2.2, hibernate-JPA-2,0-api-1.0.0,
Cảm ơn, tôi nên @Inject OtherInterface otherInterfaceImpl; và thử nghiệm với otherInterfaceImpl. Nó hoạt động! – smallufo