zoukankan      html  css  js  c++  java
  • 乱入Spring+Mybatis

      新进入一个项目,写了一个功能,就是提供一个服务(service),该服务能够查询和插入。完成后,想要用junit测试一下;发现到了DAO底层注入的SqlSession字段为空;才意识到这是一个Spring注解的项目;之前经验主要是Spring MVC方式开发使用到Spring的注解和依赖注入。另外,这个字段被注解为@Autowired(required=true),在编译器都没有被报错实例化失败,也说明了以着这种测试的方式根本就没有走Spring的容器来管理对象。

      看来是时候要好好研究一下Spring和Mybatis的一些功能本质。

      想要在非Web工程使用Spring,那么需要通过于是添加了applicationContext.xml,定义了服务类bean,然后通过下面的方式获取容器获取对象:

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 读取bean.xml中的内容
    SmallServiceImplsvr = ctx.getBean("service", SmallServiceImpl.class);// 创建bean的引用对象

      Spring的思想就是容器管理bean,所以无论是他和谁组合,还是让他管理什么,都是向Spring的容器中放入对象。那么,这种放入就有了很多种方式,一种是通过向配置文件中添加配置的传统方式,比如,下面就是添加了service的引用。

    <?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:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
        <context:annotation-config />
        <context:component-scan
            base-package="com.a.b.component, com.a.b.service, com.a.b.dao" />
        <bean id="service" class="com.a.b.service.impl.SmallServiceImpl"></bean>
    </beans>

      定义了bean就可以通过上面的代码来获取SmallServiceImpl了。但是对于这段xml有两点说明:

      1. 其实是不需要对annotation-config进行声明,因为component-scan已经具有了annotation-config的职能;

      2.component-scan可以一次性声明扫描多个包(Spring做的扫描是扫描class文件);我就是曾经有一次运行报错,就是因为有一个包没有添加到监视,导致了Spring容器创建bean失败;

      扫描的本质是基于注解(@Service,@Component,@Repository)来发现bean(免于在xml文件进行配置),扫描之后,就是“装配”,类似于Autowired声明是为了Spring容器在实例化bean的过程中来装配字段,所以扫描和装配是两个阶段,后者是基于前者,也不完全依赖(还可以基于配置文件)。

      你会发现一个现象:@Autowired声明的字段的类型都是接口,但是作为装配的类都是通过@Service/@Repository注解声明的实现类。

      另外对于基于注解的说明,对于本例而言,可以不再配置文件中声明service,可以在定义的类头声明@Service(value="service")也可;如果不指定value值,默认的bean的名称为类名首字母小写(smallServiceImp)

    @Service(value="service")
    public class SmallServiceImpl {

      通过getBean获取到了SmallService之后,在运行发现还是报错,因为执行到DAO的时候,发现那个SqlSession的字段(required=true)实例化失败,无法找到候选类;查找了很久原因;其实扫描的是指定的包,无法找到mybaits的类很正常,这个时候就是第三段那段话,和第三方组件配合的时候,第三方组件都是以bean形式定义到了Spring中;另外这个问题查了一段时间是因为我忘记了MyBatis的核心组件就是SqlSession以及SqlSessionFactory,早点想到就能知道需要将其以bean形式注入。

        <bean id="dataSource" name="dataSource"
            class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <!-- 指定连接数据库的驱动 -->
            <property name="driverClass" value="dm.jdbc.driver.DmDriver" />
            <!-- 指定连接数据库的URL -->
            <property name="jdbcUrl" value="jdbc:dm://localhost:5236" />
            <!-- 指定连接数据库的用户名 -->
            <property name="user" value="user" />
            <!-- 指定连接数据库的密码 -->
            <property name="password" value="password" />
            <!-- 指定连接池中保留的最大连接数. Default:15 -->
            <property name="maxPoolSize" value="10" />
            <!-- 指定连接池中保留的最小连接数 -->
            <property name="minPoolSize" value="3" />
            <!-- 指定连接池的初始化连接数 取值应在minPoolSize 与 maxPoolSize 之间.Default:3 -->
            <property name="initialPoolSize" value="3" />
            <!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。 Default:0 -->
            <property name="maxIdleTime" value="0" />
            <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数. Default:3 -->
            <property name="acquireIncrement" value="2" />
            <!-- JDBC的标准,用以控制数据源内加载的PreparedStatements数量。 但由于预缓存的statements属于单个connection而不是整个连接池所以设置这个参数需要考虑到多方面的因数.如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
            <property name="maxStatements" value="20" />
            <!-- 每60秒检查所有连接池中的空闲连接.Default:0 -->
            <property name="idleConnectionTestPeriod" value="60" />
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="configLocation" value="classpath:sqlmapConfig.xml"></property>
            <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
            <property name="typeAliasesPackage" value="com.a.b.vo"></property>
        </bean>
    
        <!-- 配置SQLSession模板 -->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg index="0" ref="sqlSessionFactory" />
        </bean>

      增加了三个bean,定义数据源(dataSource),定义SqlSessionFactory以及SqlSession就不多说什么了。核心就是SqlSessionFactory,dataSource字段说明了数据源信息(此次项目使用的ComboPooledDataSource进行JDBC以及连接池管理);mapperLocation,就是告知mapper文件路径,注意这里路径指的是class路径,因为Spring容器的操作都是在部署之后的环境,所以一定是claas路径;configLocation,对于mybatis的配置(比如mapper参数对象,返回对象的别名,mybatis对于缓存的一些配置都是放置在这个配置文件中;至于typeAliasesPackage,不知。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="cacheEnabled" value="true" />
            <setting name="lazyLoadingEnabled" value="true" />
            <setting name="aggressiveLazyLoading" value="false" />
            <setting name="multipleResultSetsEnabled" value="true" />
            <setting name="useColumnLabel" value="true" />
            <setting name="defaultExecutorType" value="REUSE" />
            <setting name="defaultStatementTimeout" value="25000" />
        </settings>
    
        <typeAliases>
            <package name="com.zcm.mall.vo"/>
        </typeAliases>
    
    </configuration>

      上面这个就是mybatis的配置文件。

      配置好了SqlSession/Factory信息之后,SqlSession字段可以被实例化,而且可以顺利的访问数据库了。

    小记

      1. 在mapper文件中,经常会有比较大小的情况">","<",对于这些特殊字符要么采用转义的方式,要么采用<![CDATA[ 这里写你的sql ]]>  这种方式;

      2.在mapper的sql中,可以通过在sql语句中添加<include refid="whereClause" />来添加共通的sql,比如where的过来条件(根据查询bean字段进行拼sql),可能多个select语句会共用,这个时候可以考虑使用。比如分页是一个共同的sql,可以单独放置到一个文件中(比如CommonsqlMapper.xml),然后使用的地方通过include进行引用。

    CommonSqlMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="commonSql" >
      <sql id="pageSql">
        <if test="offset != null and limit != null">
          limit #{offset}, #{limit}
        </if>
      </sql>
    </mapper>

    ASqlMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.zcm.mall.vo.AuditLog">
        <resultMap id="auditLog" type="com.a.b.vo.c">
            <id column="id" property="id" jdbcType="BIGINT" />
            <result column="log_type" property="logType" jdbcType="VARCHAR" />
            <result column="log_msg" property="log" jdbcType="VARCHAR" />
            <result column="oper_Id" property="userId" jdbcType="BIGINT" />
            <result column="oper_name" property="userName" jdbcType="VARCHAR" />
            <result column="create_date" property="createDate" jdbcType="VARCHAR" />
        </resultMap>
        <select id="select" parameterType="auditLog" resultMap="auditLog">
            select * from AUDIT_LOG
            <include refid="whereClause" />
            <include refid="commonSql.pageSql" />
        </select>

      上面的xml中有一个地方定义了resultMap,这个定义用于将数据库中查询结果和实体类进行映射之用。如果你的数据库字段定义的和实体类名称不一致,需要通过这种方式进行映射。

  • 相关阅读:
    HDU 2639 Bone Collector II (01背包,第k解)
    POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
    hihoCoder #1165 : 益智游戏 (挑战赛11 B题)
    UVA 562 Dividing coins 分硬币(01背包,简单变形)
    POJ Charm Bracelet 挑饰品 (常规01背包)
    hiho一下 第四十四周 博弈游戏·Nim游戏(直接公式解)
    UVA 624 CD(01背包,要记录路径)
    118 Pascal's Triangle 帕斯卡三角形 杨辉三角形
    117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II
    116 Populating Next Right Pointers in Each Node 每个节点的右向指针
  • 原文地址:https://www.cnblogs.com/xiashiwendao/p/6599403.html
Copyright © 2011-2022 走看看