Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 使用@Transactional时自动关联依赖项的注入失败_Spring_Hibernate_Jakarta Ee_Orm_Annotations - Fatal编程技术网

Spring 使用@Transactional时自动关联依赖项的注入失败

Spring 使用@Transactional时自动关联依赖项的注入失败,spring,hibernate,jakarta-ee,orm,annotations,Spring,Hibernate,Jakarta Ee,Orm,Annotations,我正在测试我的刀,但它不起作用。出现以下错误: Tests in error: testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested

我正在测试我的刀,但它不起作用。出现以下错误:

Tests in error: 
  testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.tsekhan.rssreader.dao.HibernateController com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController; nested exception is java.lang.IllegalArgumentException: Can not set com.tsekhan.rssreader.dao.HibernateController field com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController to $Proxy25
我的刀:

@Service
@Scope("singleton")
public class HibernateController extends HibernateDaoSupport {

    @Autowired
    public SessionFactory sessionFactory;

    @Transactional
    public void addAcount(Account account) {
        sessionFactory.getCurrentSession().saveOrUpdate(account);
    }
}
我对这个DAO的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/applicationContext.xml")
public class HibernateControllerTest {

    @Autowired
    HibernateController hibernateController;

    private Set<Channel> getTestChannelList(String channelLink) {
        Channel testChannel = new Channel();
        testChannel.setSourceLink(channelLink);
        Set<Channel> testChannelList = new HashSet<Channel>();
        testChannelList.add(testChannel);
        return testChannelList;
    }

    private Account getTestAccount(String accountLogin, String channelLink) {
        Account testAccount = new Account();
        testAccount.setAccountLogin(accountLogin);
        testAccount.setChannelList(getTestChannelList(channelLink));
        return testAccount;
    }

    @Test
    public void testAccountOperations() {
        hibernateController
                .addAcount(getTestAccount("test_login", "test_link"));
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“类路径:/applicationContext.xml”)
公共类HibernateControllerTest{
@自动连线
HibernateController HibernateController;
私有集getTestChannelList(字符串channelLink){
通道测试通道=新通道();
testChannel.setSourceLink(channelLink);
Set testChannelList=newhashset();
testChannelList.add(testChannel);
返回testChannelList;
}
私有帐户getTestAccount(字符串accountLogin,字符串channelLink){
账户testAccount=新账户();
testAccount.setAccountLogin(accountLogin);
testAccount.setChannelList(getTestChannelList(channelLink));
返回测试帐户;
}
@试验
公开作废testAccountOperations(){
冬眠控制器
.addAcount(getestaccount(“test\u登录”、“test\u链接”);
}
}
My applicationContext.xml:


org.hibernate.cfg.AnnotationConfiguration

我注意到,如果您在DAO中注释@Transactional,则bean的创建是正确的。发生了什么事?

首先,给一个DAO起个以Controller结尾的名字是很糟糕的。它非常令人困惑,Controller和DAO有着不同的用途

当您将
@Transactional
添加到服务或dao类中时,为了使spring在事务中工作,需要创建该类的代理,它是一种包装器,在执行代理类(考虑中的类是代理的)之前方法spring启动事务,在执行之后(如果没有异常完成事务),可以通过AOP和注释在spring中完成。用代码描述

public class OriginalDaoImpl implements OriginalDao extends DaoSupport {

  public void save(Object o){
      manager.save(o);
  }
}

public class ProxyDaoImpl implements OriginalDao {

    private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
    public void save(Object o){
       try{
            transaction.start();
            originalDaoImpl.save(o);
            transaction.commit(); 
       }catch(Exception e){
            transaction.rollback();
       }finally{
            //clean up code
       }
    }
}

正如你所看到的,这不是一个精确的实现,而是一个基础代码,事务如何神奇地为你工作。关键的一点是OriginalDao接口,这使得注入变得容易,因为OriginalDaoImpl和ProxyDaoImpl都实现了相同的接口。因此,它们可以互换,即代理代替原始文件。这个动态代理可以通过java动态代理在java中创建。现在的问题是,如果您的类没有实现接口,那么替换将变得更加困难。 据我所知,其中一个库CGLIB在这种情况下很有帮助,它为考虑中的类生成一个动态子类,在重写方法中,通过调用

super.save(o)
委托给原始代码来执行上述魔术

现在谈谈注射的问题

  • 创建接口并使您的dao实现该接口,spring将默认为JDK代理,因为它现在正在运行
  • 将代理目标class=“true”属性添加到
  • 就异常而言,它是抛出的,因为它期望注入的bean是“HibernateController”类型,但它不是

    你可以参考下面的链接


  • 希望这有帮助

    如果您使用的是
    springmvc
    ,请确保在
    servlet上下文文件中单独扫描特定的控制器类。否则它将扫描2次,并且事务在应用程序上下文中不可用。

    BTW,IMHO对于DAO类,最好使用
    @Repository
    注释,而不是
    @Service
    。也许您应该澄清,在注入接口时,您不需要
    proxy target class=“true”
    。另外,
    proxy target class=“true”
    将中断接口上的
    @Transactional
    。除此之外:+1.我的@Autowire不在接口上,但在类上。。。谢谢
    public class OriginalDaoImpl implements OriginalDao extends DaoSupport {
    
      public void save(Object o){
          manager.save(o);
      }
    }
    
    public class ProxyDaoImpl implements OriginalDao {
    
        private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
        public void save(Object o){
           try{
                transaction.start();
                originalDaoImpl.save(o);
                transaction.commit(); 
           }catch(Exception e){
                transaction.rollback();
           }finally{
                //clean up code
           }
        }
    }