zoukankan      html  css  js  c++  java
  • MyBatis随笔

    前一阵参与了一个项目的搭建,为了快速开发再加上学一些新东西,准备采用React+Spring MVC+MyBatis的架构。

    花了一些时间最终把Spring MVC+MyBatis打通。

    这里总结下MyBatis的使用过程,方便以后查阅。

     参考资料:

    1. http://www.mybatis.org/mybatis-3/zh/

    2. http://blog.csdn.net/isea533/article/category/2092001

    不玩儿虚的,直接上!

    环境:Intellij IDEA 12; SQLSERVER;

    既然是Spring MVC+MyBatis的架构,分service和persistence层。另外,Intellij IDEA构建多模块结构还是挺方便的,两个模块如下:

    整体的运作就是service层调用persistence层的dao来访问数据库,而MyBatis则作为数据库SQLSERVER同service层的桥梁。

    MyBatis整体来说,同Hibernate一样,是对JDBC的轻量级封装,完成ORM功能。

    从使用MyBatis和Hibernate来说,个人感觉,Hibernate更加偏向于对象化,比如Criteria和Query,创建查询对象;MyBatis则偏向于sql,将sql语句写入mapper文件中。

    总体来说,使用Hibernate需要多多少少了解它的HQL语句,而MyBatis则更注重数据库操作的专一化,即只是使用sql语句,对查询结果用resultMap封装,所以难易程度上,个人感觉MyBatis更容易一些。

    下面试着打通MyBatis和SQLSERVER......

    1. 任何开源框架的使用,肯定是要先进行配置的。

      1.1 对MyBatis来说,针对它自己的配置文件是mybatisConfig.xml(默认)。在这个项目里,因为和Spring整合,就只用到日志的配置。

    mybatisConfig.xml

    <?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="logImpl" value="SLF4J"/>
        </settings>
    </configuration>

    这里对应logImpl的value可以从源码里找到(org.apache.ibatis.session.Configuration, 该类配置了很多MyBatis的默认值),如下:

        typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
        typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
        typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
        typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
        typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
        typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
        typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

      1.2 因为同Spring整合,添加mybatis-spring依赖(maven方式)

                <dependency>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis-spring</artifactId>
                    <version>1.3.0</version>
                </dependency>

      1.3 回到数据库一端,涉及创建数据源以及基于Spring的事务管理

    persistence.properties

    # jdbc.*
    jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
    jdbc.url=jdbc:sqlserver://dbhost:dbport;databaseName=db-name;
    jdbc.user=aaa
    jdbc.password=aaa
    jdbc.initialSize=1
    jdbc.minIdle=1
    jdbc.maxActive=20
    jdbc.maxWait=60000
    jdbc.tberm=60000
    jdbc.meitm=300000
    jdbc.vq=SELECT 'x'
    jdbc.twi=true
    jdbc.tob=false
    jdbc.tor=false

    persistenceContext.xml (Part I)

    <context:property-placeholder location="classpath:persistence.properties"/>
        <!-- DataSource related -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
            <property name="initialSize" value="${jdbc.initialSize}"/>
            <property name="minIdle" value="${jdbc.minIdle}"/>
            <property name="maxActive" value="${jdbc.maxActive}"/>
            <property name="maxWait" value="${jdbc.maxWait}"/>
            <property name="timeBetweenEvictionRunsMillis" value="${jdbc.tberm}"/>
            <property name="minEvictableIdleTimeMillis" value="${jdbc.meitm}"/>
            <property name="validationQuery" value="${jdbc.vq}"/>
            <property name="testWhileIdle" value="${jdbc.twi}"/>
            <property name="testOnBorrow" value="${jdbc.tob}"/>
            <property name="testOnReturn" value="${jdbc.tor}"/>
        </bean>
    <!-- 配置Spring的事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <tx:annotation-driven transaction-manager="transactionManager" />

    这里的jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver,SQLServerDriver并没有在Maven Repository托管,而且鉴于项目基于Maven构建,将下载到的sqljdbc41.jar(jre7) install到本地,使用如下命令:

    mvn install:install-file -Dfile=sqljdbc41.jar -Dpackaging=jar -DgroupId=com.microsoft.sqlserver -DartifactId=sqljdbc -Dversion=4.1

    OK, 接下来是mybatis同Spring整合时的核心部分。

      1.4 Mybatis同Spring整合

    persistenceContext.xml (Part II)

        <!-- 配置sqlSessionFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mapperLocations" value="classpath:mapper/*.xml"/>
            <property name="configLocation" value="classpath:mybatisConfig.xml"/>
            <property name="typeAliasesPackage" value="com.chris.persistence.entity"/>
        </bean>
        <!-- 配置扫描器 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.chris.persistence.dao"/>
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        </bean>

    利用Intellij IDEA,可以看到mapperLocations对应的value呈红色,因为在resources包下并没有mapper文件夹和xml文件。

    这个时候应该停下来想想MyBatis怎么做到ORM? 总体来说,同Hibernate类似

        1. 数据库表中的记录同java bean对应

    Record:

    Java Bean:

    import java.util.Date;
    
    public class Report {
        private Integer id;
        private String name;
        private String description;
        private String owner;
        private String customer;
        private Date created;
        private String createdby;
        private Date updated;
        private String updatedby;
        private Integer version;
        private Integer clientversion;
    
        public Report(Integer id, String name, String description, String owner, String customer, Date created, String createdby, Date updated, String updatedby, Integer version, Integer clientversion) {
            this.id = id;
            this.name = name;
            this.description = description;
            this.owner = owner;
            this.customer = customer;
            this.created = created;
            this.createdby = createdby;
            this.updated = updated;
            this.updatedby = updatedby;
            this.version = version;
            this.clientversion = clientversion;
        }
    
        public Report() {
            super();
        }
    
        setter; getter...

        2. 程序调用接口方法并根据mapper文件执行sql语句

    dao层:

    import com.chris.persistence.entity.Report;
    import com.chris.persistence.entity.SubReport;
    
    import java.util.List;
    
    public interface ReportMapper {
        int deleteByPrimaryKey(Integer id);
        int insert(Report record);
        int insertSelective(Report record);
        Report selectByPrimaryKey(Integer id);
        int updateByPrimaryKeySelective(Report record);
        int updateByPrimaryKey(Report record);
        List<SubReport> selectReportListByPWID(String pwid);
    
    }

    mapper.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.chris.persistence.dao.ReportMapper">
        <resultMap id="BaseResultMap" type="com.chris.persistence.entity.Report">
            <constructor>
                <idArg column="Id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
                <arg column="Name" jdbcType="VARCHAR" javaType="java.lang.String"/>
                <arg column="Description" jdbcType="VARCHAR" javaType="java.lang.String"/>
                <arg column="Owner" jdbcType="CHAR" javaType="java.lang.String"/>
                <arg column="Customer" jdbcType="VARCHAR" javaType="java.lang.String"/>
                <arg column="Created" jdbcType="TIMESTAMP" javaType="java.util.Date"/>
                <arg column="CreatedBy" jdbcType="VARCHAR" javaType="java.lang.String"/>
                <arg column="Updated" jdbcType="TIMESTAMP" javaType="java.util.Date"/>
                <arg column="UpdatedBy" jdbcType="VARCHAR" javaType="java.lang.String"/>
                <arg column="Version" jdbcType="INTEGER" javaType="java.lang.Integer"/>
                <arg column="ClientVersion" jdbcType="INTEGER" javaType="java.lang.Integer"/>
            </constructor>
        </resultMap>
        <resultMap id="ReportListResultMap" type="SubReport">
            <result column="Id" property="id"/>
            <result column="Name" property="name"/>
            <result column="Description" property="description"/>
        </resultMap>
        <sql id="Base_Column_List">
        Id, Name, Description, Owner, Customer, Created, CreatedBy, Updated, UpdatedBy, Version, 
        ClientVersion
      </sql>
        <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
            select
            <include refid="Base_Column_List"/>
            from [Report]
            where Id = #{id,jdbcType=INTEGER}
        </select>
        <select id="selectReportListByPWID" parameterType="String" resultMap="ReportListResultMap">
          select r.[Id], r.[Name], r.[Description]
          from [Report] as r left join [Report_Access] as ra on r.[Id]=ra.[ReportId]
          left join [User] as u on u.[Id]=ra.[UserId]
          where u.[PWID] = #{pwid}
        </select>
        <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
        delete from [Report]
        where Id = #{id,jdbcType=INTEGER}
      </delete>
        <insert id="insert" parameterType="com.chris.persistence.entity.Report">
        insert into [Report] (Id, Name, Description, 
          Owner, Customer, Created, 
          CreatedBy, Updated, UpdatedBy, 
          Version, ClientVersion)
        values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, 
          #{owner,jdbcType=CHAR}, #{customer,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP}, 
          #{createdby,jdbcType=VARCHAR}, #{updated,jdbcType=TIMESTAMP}, #{updatedby,jdbcType=VARCHAR}, 
          #{version,jdbcType=INTEGER}, #{clientversion,jdbcType=INTEGER})
      </insert>
        <insert id="insertSelective" parameterType="com.chris.persistence.entity.Report">
            insert into [Report]
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="id != null">
                    Id,
                </if>
                <if test="name != null">
                    Name,
                </if>
                <if test="description != null">
                    Description,
                </if>
                <if test="owner != null">
                    Owner,
                </if>
                <if test="customer != null">
                    Customer,
                </if>
                <if test="created != null">
                    Created,
                </if>
                <if test="createdby != null">
                    CreatedBy,
                </if>
                <if test="updated != null">
                    Updated,
                </if>
                <if test="updatedby != null">
                    UpdatedBy,
                </if>
                <if test="version != null">
                    Version,
                </if>
                <if test="clientversion != null">
                    ClientVersion,
                </if>
            </trim>
            <trim prefix="values (" suffix=")" suffixOverrides=",">
                <if test="id != null">
                    #{id,jdbcType=INTEGER},
                </if>
                <if test="name != null">
                    #{name,jdbcType=VARCHAR},
                </if>
                <if test="description != null">
                    #{description,jdbcType=VARCHAR},
                </if>
                <if test="owner != null">
                    #{owner,jdbcType=CHAR},
                </if>
                <if test="customer != null">
                    #{customer,jdbcType=VARCHAR},
                </if>
                <if test="created != null">
                    #{created,jdbcType=TIMESTAMP},
                </if>
                <if test="createdby != null">
                    #{createdby,jdbcType=VARCHAR},
                </if>
                <if test="updated != null">
                    #{updated,jdbcType=TIMESTAMP},
                </if>
                <if test="updatedby != null">
                    #{updatedby,jdbcType=VARCHAR},
                </if>
                <if test="version != null">
                    #{version,jdbcType=INTEGER},
                </if>
                <if test="clientversion != null">
                    #{clientversion,jdbcType=INTEGER},
                </if>
            </trim>
        </insert>
        <update id="updateByPrimaryKeySelective" parameterType="com.chris.persistence.entity.Report">
            update [Report]
            <set>
                <if test="name != null">
                    Name = #{name,jdbcType=VARCHAR},
                </if>
                <if test="description != null">
                    Description = #{description,jdbcType=VARCHAR},
                </if>
                <if test="owner != null">
                    Owner = #{owner,jdbcType=CHAR},
                </if>
                <if test="customer != null">
                    Customer = #{customer,jdbcType=VARCHAR},
                </if>
                <if test="created != null">
                    Created = #{created,jdbcType=TIMESTAMP},
                </if>
                <if test="createdby != null">
                    CreatedBy = #{createdby,jdbcType=VARCHAR},
                </if>
                <if test="updated != null">
                    Updated = #{updated,jdbcType=TIMESTAMP},
                </if>
                <if test="updatedby != null">
                    UpdatedBy = #{updatedby,jdbcType=VARCHAR},
                </if>
                <if test="version != null">
                    Version = #{version,jdbcType=INTEGER},
                </if>
                <if test="clientversion != null">
                    ClientVersion = #{clientversion,jdbcType=INTEGER},
                </if>
            </set>
            where Id = #{id,jdbcType=INTEGER}
        </update>
        <update id="updateByPrimaryKey" parameterType="com.chris.persistence.entity.Report">
        update [Report]
        set Name = #{name,jdbcType=VARCHAR},
          Description = #{description,jdbcType=VARCHAR},
          Owner = #{owner,jdbcType=CHAR},
          Customer = #{customer,jdbcType=VARCHAR},
          Created = #{created,jdbcType=TIMESTAMP},
          CreatedBy = #{createdby,jdbcType=VARCHAR},
          Updated = #{updated,jdbcType=TIMESTAMP},
          UpdatedBy = #{updatedby,jdbcType=VARCHAR},
          Version = #{version,jdbcType=INTEGER},
          ClientVersion = #{clientversion,jdbcType=INTEGER}
        where Id = #{id,jdbcType=INTEGER}
      </update>
    </mapper>

    OK, 写到这里应该明白MyBatis的最核心部分是mapper.xml。

    对接触MyBatis时间不长的人来说,最快的办法是有个现成的mapper.xml在那可供参考,然后慢慢熟悉mapper.xml的语法和写法,而不是详细的阅读mapper.xml如何写。

    有个mybatis generator工具,可以用来帮助生成mapper.xml。

        添加maven依赖:

    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.5</version>
    </dependency>

        添加对应的配置文件generatorConfig.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
        <properties resource="persistence.properties"/>
        <context id="default" targetRuntime="MyBatis3">
            <commentGenerator>
                <property name="suppressDate" value="true"/>
                <property name="suppressAllComments" value="true"/>
            </commentGenerator>
            <jdbcConnection
                    driverClass="${jdbc.driverClassName}"
                    connectionURL="${jdbc.url}"
                    userId="${jdbc.user}"
                    password="${jdbc.password}">
            </jdbcConnection>
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false"/>
            </javaTypeResolver>
            <javaModelGenerator targetPackage="com.chris.persistence.entity"
                                targetProject="src/main/java">
                <property name="enableSubPackages" value="false"/>
                <property name="constructorBased" value="true"/>
                <property name="trimStrings" value="true"/>
                <property name="immutable" value="false"/>
            </javaModelGenerator>
            <sqlMapGenerator targetPackage="mapper"
                             targetProject="src/main/resources">
                <property name="enableSubPackages" value="false"/>
            </sqlMapGenerator>
            <javaClientGenerator targetPackage="com.chris.persistence.dao"
                                 targetProject="src/main/java" type="XMLMAPPER">
                <property name="enableSubPackages" value="true"/>
            </javaClientGenerator>
    
            <table tableName="User" domainObjectName="User"
                   enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
            <table tableName="Resource" domainObjectName="Resource"
                   enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
            <table tableName="Version" domainObjectName="Version"
                   enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
            <table tableName="Report" domainObjectName="Report"
                   enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
            <table tableName="Report_Access" domainObjectName="Report_Access"
                   enableCountByExample="false" enableUpdateByExample="false"
                   enableDeleteByExample="false" enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
        </context>
    </generatorConfiguration>

         用maven build, mybatis-generator:generate -e

        

        之后生成dao和entity

        

    在使用mybatis generator工具时,每次运行mybatis-generator:generate -e,dao和entity会被覆盖,但mapper.xml则是追加的方式被修改,所以注意在mybatis-generator之前删除mapper.xml文件。

    OK, 总的来说,在使用MyBatis做ORM框架时,dao作为entity和DB record的桥梁,而关于java bean和database row的mapping信息则通过mapper.xml获得。

    在MyBatis中,sql写在mapper.xml文件中,而且重点在于如何利用好resultMap和动态sql

    内容总结:

    (1) MyBatis配置; (2) MyBatis与Spring整合; (3) Mybatis generator使用

    Done! 

  • 相关阅读:
    筛选数据
    sed实现路径替换
    mask rcnn
    py faster rcnn+ 1080Ti+cudnn5.0
    反对迭代0:停止拖延,开始迭代
    故事点数是对工时的度量
    放弃在每日站会上按成员逐个发言
    So Easy!7000元Scrum认证课1元抢~
    用leangoo怎么做需求管理及规划?(产品Backlog、用户故事)
    怎么用leangoo做需求管理?(用户故事地图)
  • 原文地址:https://www.cnblogs.com/hello-yz/p/6927965.html
Copyright © 2011-2022 走看看