Fork me on GitHub

配置spring的mapperScannerConfigurer产生java.lang.StackOverflowError

java.lang.StackOverflowError

但配置mybatis-spring时报java.lang.StackOverflowError

环境:

配置时使用的是MapperScannerConfigurer(注:用此方式会自动创建basePackage配置中指定的包下的接口的实现类,在容器中隐式生成id为接口名小写的bean)

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zx.mapper"/>
    </bean>

mapper接口:

public interface UserMapper {
    //查询所有用户
    @Select("select * from User")
    List<User> selectUser();
    //添加用户
    int addUser(User user);
    //删除用户
    int deleteUser(int id);
}

配置事务 aop织入

事务管理器配置情况:

<!--配置声明式事务 方式二-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--结合aop实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <!--配置事务的传播特性:propagation=-->
        <tx:attributes>
<!--            <tx:method name="addUser" propagation="REQUIRED"/>-->
<!--            <tx:method name="deleteUser" propagation="REQUIRED"/>-->
<!--            <tx:method name="update" propagation="REQUIRED"/>-->
<!--            <tx:method name="selectUser" propagation="REQUIRED" read-only="true"/>-->
            <!--此条等同于上面四条-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <!--切入点:com.zx.mapper包下的所有类的所有方法(任意参数)-->
        <aop:pointcut id="txPointCut" expression="execution(* com.zx.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

然后我写了一个实现类来测试事务回滚

public class UserMapperImpl implements UserMapper{

    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public List<User> selectUser() {
        System.out.println("-----why-----");
        //添加用户
        User user = new User();
        user.setId(6);
        user.setName("地动仪");
        user.setPwd("666");
        addUser(user);
        //删除用户(故意将sql语句写错,看是否回滚)
        deleteUser(6);

        return userMapper.selectUser();
    }

    @Override
    public int addUser(User user) {
        return userMapper.addUser(user);
    }

    @Override
    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }
}

实现类的bean(注意异常就是这里)

<!--userMapper的实现类-->
    <bean id="userMapper" class="com.zx.mapper.UserMapperImpl">
        <property name="userMapper" ref="userMapper"/>
    </bean>
</beans>

测试方法:

//测试事务
    @Test
    public void TestTransaction(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-mybatis.xml");
        UserMapper userMapper = (UserMapper) context.getBean("userMapper");
        List<User> users = userMapper.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
    }

解决方法很简单,就是将这个实现类的id更改一下防止和隐式的userMapper重名。

难点就是要理解mapperScannerConfigurer会自动代理生成同名的接口实现类

注意:如果通过类型来获取bean的话会报org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zx.mapper.UserMapperImpl' available

原因同上:已经存在两个同名的实现类了所以只能改id值

posted @ 2021-03-01 15:21  雾深  阅读(135)  评论(0编辑  收藏  举报