MyBatis

为什么要使用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;

@Service
public 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();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值