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! 

  • 相关阅读:
    Android开发之Sqlite的使用
    ZOJ 3607 Lazier Salesgirl
    ZOJ 3769 Diablo III
    ZOJ 2856 Happy Life
    Ural 1119 Metro
    Ural 1146 Maximum Sum
    HDU 1003 Max Sum
    HDU 1160 FatMouse's Speed
    Ural 1073 Square Country
    Ural 1260 Nudnik Photographer
  • 原文地址:https://www.cnblogs.com/hello-yz/p/6927965.html
Copyright © 2011-2022 走看看