• SSM框架(1):使用Maven搭建SSM项目实践


    一、推荐阅读

    1. MyBatis(1)——快速入门
    2. MyBatis(2)——MyBatis 深入学习
    3. Maven整合SSM框架

    二、实践中的问题 - SpringSpringMVC

    问题一:@Service 和 @Resource注解的误用 

    两个注解的作用:
    @Service("XXX"):用在类上。相当于将这个类定义为一个bean,bean的名称为XXX; @Resource(name="xxx"):用在类的引用型属性上。当需要在某个类中定义一个属性,并且该属性是一个已在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name="XXX")注解,相当于为该属性注入一个名称为xxx的bean。
    • 知识扩展:

      Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。 

      @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

      @Resource装配顺序

    1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
    2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
    3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
    4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配

    三、实践中的问题 - MyBatis

    问题一:MyBatis动态代理实例化DAO接口时报错,提示无法实例化扫描类 MapperScannerConigurer

    报错信息如下:
     Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0'
    //解决办法:在配置bena:MapperScannerConigurer时,使用参数sqlSessionFactoryBeanName来设置工厂类实例
    <!-- 配置扫描DAO 接口包,动态实现DAO接口实例,注入到Spring容器中进行管理 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 注入SqlSession工厂对象:SqlSessionFactoryBean -->
    <!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!-- 指定要扫描的DAO接口所在包 -->
    <property name="basePackage" value="com.newbie.dao"/>
    </bean>
    <!-- 配置工厂对象: SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--注入数据库连接池 -->
    <property name="dataSource" ref="dataSource"/>
    <!--扫描com.newbie.domain包,使用类的别名(默认首字母小写) -->
    <property name="typeAliasesPackage" value="com.newbie.domain"/>
    <!-- 扫描sqlMapper配置文件:userMapper.xml-->
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>
    原因分析:
      MapperScannerConigurer实际是在解析加载bean定义阶段实例化的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,但是,此时PropertyPlaceholderConfigurer还没来得及替换定义中的变量数据,导致把表达式当作字符串复制了。
    
    解决办法:
    第一种方式:在配置bena:MapperScannerConigurer时,使用参数sqlSessionFactoryBeanName来设置工厂类实例.原理:使用sqlSessionFactoryBeanName注入,不会立即初始化sqlSessionFactory, 所以不会引发提前初始化问题。
        即:
      修改 property name="sqlSessionFactory" ref="sqlSessionFactory" 
      改为 property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"
    
    第二种:直接删掉。原理:在配置bena:MapperScannerConigurer时,不配置sqlSessionFactory,由容器自动注入依赖。

    问题二:动态实例接口IUserDAO时,接口中的selectAll()方法没有实现

    报错信息:
    org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.newbie.dao.IUserDAO.selectAll
    原因分析:
    检查UserMapper.xml文件中的mapper配置信息,发现namespace="***"属性值不是IUserDAO的全类名。
    
    解决办法:
    修改namespace属性值,改为namespace="com.newbie.dao.IUserDAO"
    <!-- mapper配置文件,其中namespace指定要动态实例的DAO接口全局类名称 -->
    <mapper namespace="com.newbie.dao.IUserDAO">
    • 知识扩展:Invalid bound statement (not found)错误的原因是:接口IUserDAO 和 配置文件UserMapper.xml之间匹配有问题。

      排查步骤:

        (1)检查配置的UserMapper.xml的路径是否正确;

        (2)检查UserMapper.xml 所在的package名称 和 接口IUserDAO 所在的包名称是否相同;

        (3)接口IUserDAO中的方法,在配置文件UserMapper.xml 中是否存在;

        (4)接口IUserDAO中的方法返回值是Lis<User>,而UserMapper.xml中对应的select节点是否配置有ResultMap;

       

  • 相关阅读:
    mysql常用技能分享
    php生成器使用总结
    MySQL索引使用方法和性能优化
    servlet相关
    UML图
    How Tomcat Works
    字符串编码
    高效工作
    php 设计模式总结
    python之装饰器
  • 原文地址:https://www.cnblogs.com/newbie27/p/10817951.html
Copyright © 2020-2023  润新知