MyBatis

来源:互联网 发布:win10 linux bash 编辑:程序博客网 时间:2024/05/22 17:10

为什么要使用MyBatis?

  1. MyBatis是介于纯手工的JDBC和全自动的Hibernate之间的一个半自动化的持久层框架。
  2. JDBC:SQL夹杂在Java代码块里,耦合度高,维护不易且实际开发需求中sql有变化时改起来太麻烦了,而且功能简单
  3. Hibernate是一种全自动的框架,旨在消除sql,开发人员即使不懂任何sql语句,也能实现对象与数据记录之间的映射,简单的运用还是非常方便的。但是因为sql命令都是Hibernate内部自动生产的,不容易做特殊优化,如果要实现复杂查询的定制语句,还需要学习HDL,增大了学习的负担。
  4. 对于开发人员而言,核心sql还是需要自己定制和优化的,MyBatis将sql和java编码分开,功能边界清晰,一个专注数据,一个专注业务。

接口文件和XML

接口文件EmployeeMapper.java

package com.zc.mybatis.dao;import com.zc.mybatis.bean.Employee;public interface EmployeeMapper {       //传入单个参数:mybatis不会做特殊处理,    //#{参数名/任意名}:取出参数值    public Employee getEmpById(Integer id);    /*多个参数:mybatis会做特殊处理。     多个参数会被封装成 一个map,        key:param1...paramN,或者参数的索引也可以        value:传入的参数值    #{}就是从map中获取指定的key的值;    【命名参数】:明确指定封装参数时map的key;@Param("id")    多个参数会被封装成 一个map,        key:使用@Param注解指定的值        value:参数值    #{指定的key}取出对应的参数值*/    public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);}//select返回List    public List<Employee> getEmpsByLastNameLike(String lastName);

XML文件EmployeeMapper.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.zc.mybatis.dao.EmployeeMapper"><!-- namespace:名称空间;指定为接口的全类名id:唯一标识resultType:返回值类型#{id}:从传递过来的参数中取出id值public Employee getEmpById(Integer id); -->    <select id="getEmpById" resultType="com.zc.mybatis.bean.Employee">        select id,last_name lastName,email,gender from tbl_employee where id = #{id}    </select>    <!--  public Employee getEmpByIdAndLastName(Integer id,String lastName);-->    <select id="getEmpByIdAndLastName" resultType="com.zc.mybatis.bean.Employee">        select * from tbl_employee where id = #{id} and last_name=#{lastName}    </select>    <!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->    <!--resultType:如果返回的是一个集合,要写集合中元素的类型  -->    <select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee where last_name like #{lastName}    </select></mapper>

MyBatis的全局配置文件mybatis-config.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>    <!--        1、mybatis可以使用properties来引入外部properties配置文件的内容;        resource:引入类路径下的资源        url:引入网络路径或者磁盘路径下的资源      -->    <properties resource="dbconfig.properties"></properties>    <!--         2、settings包含很多重要的设置项        setting:用来设置每一个设置项            name:设置项名            value:设置项取值     -->     <!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。-->    <settings>        <setting name="mapUnderscoreToCamelCase" value="true"/>    </settings>    <!-- 3、typeAliases:别名处理器:可以为我们的java类型起别名             别名不区分大小写    -->    <typeAliases>        <!-- 1、typeAlias:为某个java类型起别名                type:指定要起别名的类型全类名;默认别名就是类名小写;employee                alias:指定新的别名         -->        <!-- <typeAlias type="com.zc.mybatis.bean.Employee" alias="emp"/> -->        <!-- 2、package:为某个包下的所有类批量起别名                 name:指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名(类名小写),)        -->        <package name="com.zc.mybatis.bean"/>        <!-- 3、批量起别名的情况下,使用@Alias注解为某个类型指定新的别名 -->    </typeAliases>    <!--         4、environments:环境们,mybatis可以配置多种环境 ,default指定使用某种环境。可以达到快速切换环境。            environment:配置一个具体的环境信息;必须有两个标签;id代表当前环境的唯一标识                transactionManager:事务管理器;                    type:事务管理器的类型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory)                        自定义事务管理器:实现TransactionFactory接口.type指定为全类名                dataSource:数据源;                    type:数据源类型;UNPOOLED(UnpooledDataSourceFactory)                                |POOLED(PooledDataSourceFactory)                                |JNDI(JndiDataSourceFactory)                    自定义数据源:实现DataSourceFactory接口,type是全类名         -->    <environments default="dev_mysql">        <environment id="dev_mysql">            <transactionManager type="JDBC"></transactionManager>            <dataSource type="POOLED">                <property name="driver" value="${jdbc.driver}" />                <property name="url" value="${jdbc.url}" />                <property name="username" value="${jdbc.username}" />                <property name="password" value="${jdbc.password}" />            </dataSource>        </environment>        <environment id="dev_oracle">            <transactionManager type="JDBC" />            <dataSource type="POOLED">                <property name="driver" value="${orcl.driver}" />                <property name="url" value="${orcl.url}" />                <property name="username" value="${orcl.username}" />                <property name="password" value="${orcl.password}" />            </dataSource>        </environment>    </environments>    <!-- 5、databaseIdProvider:支持多数据库厂商的;         type="DB_VENDOR":VendorDatabaseIdProvider            作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;            MySQL,Oracle,SQL Server,xxxx      -->    <databaseIdProvider type="DB_VENDOR">        <!-- 为不同的数据库厂商起别名 -->        <property name="MySQL" value="mysql"/>        <property name="Oracle" value="oracle"/>        <property name="SQL Server" value="sqlserver"/>    </databaseIdProvider>    <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->    <!-- 6、mappers:将sql映射注册到全局配置中 -->    <mappers>        <!--             mapper:注册一个sql映射                 注册配置文件                resource:引用类路径下的sql映射文件                    mybatis/mapper/EmployeeMapper.xml                url:引用网路路径或者磁盘路径下的sql映射文件                    file:///var/mappers/AuthorMapper.xml                注册接口                class:引用(注册)接口,                    1、有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下;                    2、没有sql映射文件,所有的sql都是利用注解写在接口上;                    推荐:                        比较重要的,复杂的Dao接口我们来写sql映射文件                        不重要,简单的Dao接口为了开发快速可以使用注解;        -->        <!-- <mapper resource="mybatis/mapper/EmployeeMapper.xml"/> -->        <!-- <mapper class="com.zc.mybatis.dao.EmployeeMapperAnnotation"/> -->        <!-- 批量注册: -->        <package name="com.zc.mybatis.dao"/>    </mappers></configuration>

参数处理

  单个参数:MyBatis不会做特殊处理。 #{参数名}:取出参数值。

public Employee getEmpById(Integer id);

  多个参数:MyBatis会做特殊处理,多个参数会被封装成一个map。要使用命名@Param("参数名")明确指定封装参数时map的key。
    key:使用@Param注解指定的值。
    value:参数值
  使用#{指定的key}就可以取出对应的参数值。

    <!--public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);-->    <select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee where id = #{id} and last_name=#{lastName}    </select>

  POJO: 如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入POJO。#{属性名}:取出传入的POJO的属性值。

  Map:如果多个参数不是业务模型中的数据,没有对应的POJO,为了方便,我们也可以传入map。#{key}:取出map中对应的值。  

    <!-- public Employee getEmpByMap(Map<String, Object> map); -->    <select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee">        select * from tb1 where id=#{id} and last_name=#{lastName}    </select>

  TO:如果多个参数不是业务模型中的数据,但是经常要使用,推荐编写一个TO(Transfer Object)数据传输对象。
Page{
  int index;
  int size;
}    

参数值的获取

  #{}:可以获取map中的值或者pojo对象属性的值;
  ${}:可以获取map中的值或者pojo对象属性的值;

select * from tbl_employee where id=${id} and last_name=#{lastName}

  运行结果:Preparing: select * from tbl_employee where id=2 and last_name=?

  区别: 

  • #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
  • ${}:取出的值直接拼装在sql语句中;会有安全问题。
  • 大多情况下,我们去参数的值都应该去使用#{};在原生jdbc不支持占位符的地方我们就可以使用${}进行取值,比如分表、排序等。如:
    ① 按照年份分表拆分:select * from ${year}_salary where xxx;
    ② 排序:select * from tbl_employee order by ${f_name} ${order}

select返回

  • 返回List
    <!-- public List<Employee> getEmpsByLastNameLike(String lastName); --><!--如getEmpsByLastNameLike("%e%")-->    <!--resultType:如果返回的是一个集合,要写集合中元素的类型  -->    <select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee where last_name like #{lastName}    </select>
  • 返回一条记录的map,key就是列名,值就是对应的值
    <!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->    <select id="getEmpByIdReturnMap" resultType="map"><!--mybatis已经给map取了别名-->        select * from tbl_employee where id=#{id}    </select>
  • 多条记录封装一个map:如Map<Integer,Employee>,其中键是这条记录的主键,值是记录封装后的javaBean
    <!--    //告诉MyBatis封装这个map的时候使用哪个属性作为主键    @MapKey("id")    public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);      -->    <select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee where last_name like #{lastName}    </select>

动态SQL

  • if test 和where
     <!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->     <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->     <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee        <!-- where -->        <where>            <!-- test:判断表达式(OGNL)            使用if  test从参数中取值进行判断,遇见特殊符号写转义字符:            如&&:&amp;&amp;  "":&quot;&quot;            -->            <if test="id!=null">                id=#{id}            </if>            <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">                <!-注意and要放在前面,最后一句sql语句的拼装会出现问题--->                and last_name like #{lastName}            </if>            <if test="email!=null and email.trim()!=&quot;&quot;">                and email=#{email}            </if>             <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->            <if test="gender==0 or gender==1">                and gender=#{gender}            </if>        </where>     </select>
  • choose
     <!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->     <select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee         <where>            <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->            <choose>                <when test="id!=null">                    id=#{id}                </when>                <when test="lastName!=null">                    last_name like #{lastName}                </when>                <when test="email!=null">                    email = #{email}                </when>                <otherwise>                    gender = 0                </otherwise>            </choose>        </where>     </select>
  • update和set
     <!--public void updateEmp(Employee employee);  -->     <update id="updateEmp">        <!-- Set标签的使用 -->        update tbl_employee         <set>            <if test="lastName!=null">                last_name=#{lastName},            </if>            <if test="email!=null">                email=#{email},            </if>            <if test="gender!=null">                gender=#{gender}            </if>        </set>        where id=#{id}      </update>
  • for each

取元素:

     <!--public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids); -->     <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">        select * from tbl_employee where id in        <!--            collection:指定要遍历的集合:                list类型的参数会特殊处理封装在map中,map的key就叫list            item:将当前遍历出的元素赋值给指定的变量            separator:每个元素之间的分隔符            open:遍历出所有结果拼接一个开始的字符            close:遍历出所有结果拼接一个结束的字符            index:索引。遍历list的时候是index就是索引,item就是当前值                          遍历map的时候index表示的就是map的key,item就是map的值            #{变量名}就能取出变量的值也就是当前遍历出的元素          -->        <foreach collection="ids" item="item_id" separator=","            open="(" close=")">            #{item_id}        </foreach>     </select>

存元素:

     <!-- 批量保存 -->     <!--public void addEmps(@Param("emps")List<Employee> emps);  -->     <!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->    <insert id="addEmps">        insert into tbl_employee(last_name,email,gender,d_id)         values        <foreach collection="emps" item="emp" separator=",">            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})        </foreach>     </insert>
  • 抽取可重用的sql片段
    <!--1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用        2、include来引用已经抽取的sql:-->        <sql id="insertColumn">            last_name,email,gender,d_id        </sql>        <insert id="addEmps">        insert into tbl_employee(            <include refid="insertColumn"></include>        )         values        <foreach collection="emps" item="emp" separator=",">            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})        </foreach>     </insert>

MyBatis逆向工程

  MyBatis Generator简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查(targetRuntime=”MyBatis3Simple”),以及QBC((Query By Criteria,按标准查询)风格的条件查询(targetRuntime=”MyBatis3”)。但是表连接、存储过程等这些复杂的SQL定义需要我们手工编写。
mbg.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>    <!--targetRuntime="MyBatis3"mbg会生成带动态sql的crud-->    <context id="DB2Tables" targetRuntime="MyBatis3">        <commentGenerator>            <property name="suppressAllComments" value="true" />        </commentGenerator>        <!-- 配置数据库连接 -->        <jdbcConnection driverClass="com.mysql.jdbc.Driver"            connectionURL="jdbc:mysql://localhost:3306/ssm_crud" userId="root"            password="123456">        </jdbcConnection>        <javaTypeResolver>            <property name="forceBigDecimals" value="false" />        </javaTypeResolver>        <!-- 指定javaBean生成的位置 -->        <javaModelGenerator targetPackage="com.atguigu.crud.bean"            targetProject=".\src\main\java">            <property name="enableSubPackages" value="true" />            <property name="trimStrings" value="true" />        </javaModelGenerator>        <!--指定sql映射文件生成的位置 -->        <sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">            <property name="enableSubPackages" value="true" />        </sqlMapGenerator>        <!-- 指定dao接口生成的位置,mapper接口 -->        <javaClientGenerator type="XMLMAPPER"            targetPackage="com.atguigu.crud.dao" targetProject=".\src\main\java">            <property name="enableSubPackages" value="true" />        </javaClientGenerator>        <!-- table指定每个表的生成策略,根据表创建相应的javaBean(名字用domainObjectName指定)  -->        <table tableName="tbl_emp" domainObjectName="Employee"></table>        <table tableName="tbl_dept" domainObjectName="Department"></table>    </context></generatorConfiguration>

分页查询

在mybatis-config.xml中添加:

    <plugins>        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>    </plugins>

批量查询

applicationContext.xml

    <!--创建出SqlSessionFactory对象  -->    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">        <property name="dataSource" ref="dataSource"></property>        <!-- configLocation指定全局配置文件的位置 -->        <property name="configLocation" value="classpath:mybatis-config.xml"></property>        <!--mapperLocations: 指定mapper文件的位置-->        <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>    </bean>    <!--配置一个可以进行批量执行的sqlSession  -->    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>        <constructor-arg name="executorType" value="BATCH"></constructor-arg>    </bean>

然后在sercive中加入SqlSession的注解

package com.atguigu.mybatis.service;import java.util.List;import org.apache.ibatis.session.SqlSession;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.atguigu.mybatis.bean.Employee;import com.atguigu.mybatis.dao.EmployeeMapper;@Servicepublic class EmployeeService {    @Autowired    private EmployeeMapper employeeMapper;    @Autowired    private SqlSession sqlSession;    public List<Employee> getEmps(){        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);        for (int i = 0; i < 10000; i++) {            mapper.addEmp(new Employee(UUID.randomUUID().toString().substring(0, 5), "b", "1"));        }        return employeeMapper.getEmps();    }}
原创粉丝点击