【问题标题】:@Transactional annotation causing incompatible return types error on entity@Transactional 注释导致实体上的返回类型不兼容错误
【发布时间】:2011-09-21 12:19:22
【问题描述】:

我有一个在 Spring MVC 中开发的 Restful Web 服务,它当前返回农民信息,并允许在数据库中删除和添加新农民。在扩展 Web 服务以包含农民顾问时,只要将事务注释添加到顾问 DAO 实现,我就会收到以下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'advisorDAO' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: methods with same signature getAdvisors() but incompatible return types: [interface java.util.List, class [Lorg.springframework.aop.Advisor;]

关于这个错误的奇怪之处在于,系统在将注释添加到类之前可以正常编译并且符合预期,但是由于我需要能够将实体持久保存到数据库中,因此需要事务。我知道错误的含义,但我不知道为什么这只是使用注释时的问题,甚至没有应用于编译器抱怨的方法。

Advisors DAO 界面:

public interface AdvisorDAO {
   public List<Advisor> getAdvisors();
   public Advisor getAdvisorByPk(int id);   
   public Advisor getAdvisorByFarmerID(int id);
   public Advisor getAdvisorByAdvisorID(int id);    
   public void saveAdvisor(Advisor advisor);
   public void deleteAdvisor(Advisor advisor);
   public void updateAdvisor (Advisor advisor);
}

接口实现:

public class JpaAdvisorDAO implements AdvisorDAO {

@PersistenceContext
private EntityManager entityManager;

public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}

@Override
public List<Advisor> getAdvisors() {
    return entityManager.createNamedQuery("Advisor.findAll").getResultList();
}

@Override
public Advisor getAdvisorByPk(int id) {
    Query query = entityManager.createNamedQuery("Advisor.findByPK");
    query.setParameter("advisorPk", id);
    return (Advisor) query.getSingleResult();
}   

@Override
public Advisor getAdvisorByFarmerID(int id) {
    Query query = entityManager.createNamedQuery("Advisor.findByFarmerId");
    query.setParameter("farmerId", id);
    return (Advisor) query.getSingleResult();
}

@Override
public Advisor getAdvisorByAdvisorID(int id) {
    Query query = entityManager.createNamedQuery("Advisor.findByAdvisorId");
    query.setParameter("advisorId", id);
    return (Advisor) query.getSingleResult();  
}    

@Override
@Transactional
public void saveAdvisor(Advisor advisor) {
    entityManager.persist(advisor);
}

@Override
@Transactional
public void deleteAdvisor(Advisor advisor) {
    entityManager.remove(entityManager.getReference(Advisor.class, advisor.getAdvisorPk()));

}

@Override
@Transactional
public void updateAdvisor (Advisor advisor) {
    entityManager.merge(advisor);
}

使用的上下文文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/aop 
      http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/context 
      http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc">


<bean id="farmerDAO" class="com.test.cmsservice.persistance.JpaFarmerDAO" />
<bean id="advisorDAO" class="com.test.cmsservice.persistance.JpaAdvisorDAO" />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="SpringRestService"/>
    <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="false"/>
                <property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"/>
            </bean>
        </property>
</bean> 
<context:annotation-config />
  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
    <property name="url" value="jdbc:derby://localhost:1527/SpringDBTest"/>
    <property name="username" value="APP"/>
    <property name="password" value="app"/>
  </bean>
  <tx:annotation-driven />
  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
  </bean>
  <bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

【问题讨论】:

    标签: java hibernate spring spring-transactions


    【解决方案1】:

    添加注解不能改变返回类型。

    首先,您可能导入了错误的类型 - Advisor 也是一个弹簧类,因此请修正您的导入。

    然后我怀疑你有一个旧版本的接口或其由类加载器加载的实现。异常消息表明其中一个方法返回List&lt;Advisor&gt;,另一个返回-Advisor[]。确保所有内容都已清理并保持最新状态。

    【讨论】:

    • 我已经检查了我的导入并且它们是正确的类(我重构了该类,因此可以肯定的是它被称为 FarmerAdvisor)但是这不太可能是问题,因为 get 方法在添加事务注释之前工作到接口实现。同样不幸的是,它不能是接口的旧实现,因为这是一个新实现,它总是返回一个列表,并且该实现在没有事务注释的情况下再次工作:(
    • 啊,你的帖子让我意识到问题是应用程序出于某种原因调用了 getAdvisors() 的 Spring 顾问版本,而不是我的实现,我不知道为什么,但通过更改我的方法名称那个解决了问题。在所有的机会中,我会尝试实现一个名为advisors的类,哈哈。谢谢你的帮助,让我免于头痛!
    猜你喜欢
    • 2021-04-15
    • 2011-08-26
    • 1970-01-01
    • 2022-12-15
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    相关资源
    最近更新 更多