MyBatis(整理)

MyBatis

1. 简介

MyBatis是一个基于Java的持久化成框架。

MyBatis支持定制化SQL。

MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO映射成数据可以中的记录。

MyBatis对于开发人员来说,核心SQL还是需要自己优化。

SQL和Java编码分开,功能边界清晰,一个专注业务,一个专注数据。

耦合性低方便后期维护。

2. HelloWorld

1)导入jar包和log4j的jar包还有log4j的xml配置文件

2)在数据库中创建MyBatis的表并在modul中创建Employee类

package com.atguigu.mybatis.mapper;

import com.atguigu.mybatis.entities.Employee;

public interface EmployeeMapper {
    Employee getEmployeeById(Integer id);
    void insertEmployee(Employee employee);
}

3)创建接口,增删改查

4)创建MyBatis的sql映射文件

​ ①参考MyBatis官方文档创建EmployeeMapper.xml映射文件

②完成两个绑定

​ a)标签中的namespace属性必须设置为Mapper接口的全类名

​ b)Mapper映射文件中的增删改查标签的id必须指定成Mapper接口中的方法名

<?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">
<!--namespace属性设置为接口的全类名-->
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">
	<!-- 
		id属性:设置为接口中的方法名
		resultType属性:设置为方法的返回值的类型的全类名
		resultMap属性:方法的返回值是Map 要么是type要么是map
	-->
    <select id="getEmployeeById" resultType="com.atguigu.mybatis.entites.Employee">
        select id,last_name,email,salary,dept_id deptId
        from employees
        where id = #{id}
    </select>
</mapper>

5)创建MyBatis全局配置文件

<?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>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

6)创建测试文件

public class MyBatisTest{
    
    // 1.获取SqlSessionFactory
    public SqlSessionFactory getSqlSessionFactory() throw IOException{
        // 2.设置全局配置文件的路径
        String resource = "mybatis-config.xml";
        // 3.将类路径下的全局配置文件读成输入流
        Inputstream inputStream = Resources.getResourceAsStream(resource);
        // 4.构建SqlSessionFactory
       	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().bulid(inputStream);
        return sqlSessionFactory;
    }
    
    /*
    	测试HelloWorld
    */
    @Test
    public void testHelloWorld() throw IOException{
        
        // 5.获取SqlSessionFactory
        SqlSessionFactory sqlSqlSessionFactory = getSqlSessionFactory();
        // 6.获取sqlSessionFactory,相当于原来的Connection
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
            // 7.获取Mapper对象
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            // 8.调用EmployeeMapper中查询一个员工的方法
            Emplpyee employeeById = employeeMapper.getEmployeeById(1);
            System.out.println("emplpyeeById = "+employeeById);
        }finally{
            // 9.关闭sqlSession
            sqlSession.close();
        }
    }
}

3. 增删改查

获取SqlSessionFactory

public SqlSessionFactory getSqlSessionFactory() throws IOException {
    // 2.设置全局配置文件的路径
    String resource = "mybatis-config.xml";
    // 3.将类路径下的全局配置文件读成输入流
    InputStream inputStream = Resources.getResourceAsStream(resource);
    // 4.构建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    return sqlSessionFactory;
}

在EmployeeMapper的配置文件中写入增删改查的语句和方法

    <!--查找-->
    <select id="getEmployeeById" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name lastName,email,salary,dept_id deptId
               from employees
          where id = #{id}
    </select>
    <!--添加
        parameterType属性:指定方法中的入参类型也可以不指定,MyBatis会自动推断
        useGeneratedKeys属性:设置是和否获取数据库中的主键值
            注意;数据库必须支持自增主键
        keyProperty属性:设置获取的主键值赋给POJO的那个属性
    -->
    <insert id="insertEmployee" useGeneratedKeys="true" keyProperty="id">
        insert into employees(last_name,email,salary,dept_id)
        values (#{lastName},#{email},#{salary},#{deptId})
    </insert>
    <!--删除-->
    <delete id="deleteEmployeeById">
        delete from employees where id = #{id}
    </delete>

    <!--更新-->
    <update id="updateEmployee">
        update employees set
                             last_name = #{lastName},
                             email = #{email},
                             salary = #{salary},
                             dept_id = #{deptId}
        where id = #{id}
    </update>

在测试类中首先要获取SqlSessionFactory

再调用SqlSessionFactory的openSession方法

获取Mapper对象,利用Mapper对象调用Mapper对象中的增删改查的方法

增删改需要手动提交sqlSeesion.commin()

最后在finally块中关闭sqlSession

sqlSession.close();

3. MyBatis全局配置文件

1)properties标签

可以引入外部的属性文件配置数据源

resource属性:引入类路径下的属性文件

url属性:引入网络或者磁盘上的属性文件

<propertirs resource="db.properties">
    <property name="password" value="root2"/>
</propertirs>

2) ★settings标签

settings标签是用来设置MyBatis中的重要配置,它们会改变MyBatis的运行行为。

<settings>
	<!--开启驼峰命名自动映射-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

3)typeAliases标签

用来给POJO类设置别名

通过子标签typeAlias设置别名

​ type属性:指定要起别名的全类名

​ alias属性:指定别名,如果不指定,默认首字母小写,别名不区分大小写

通过子标签package批量设置别名

​ name属性:name属性:指定包名,会该包下所有的类都指定了别名

<typeAliases>
    <!--        <typeAlias type="com.atguigu.mybatis.entities.Employee" alias="employee"></typeAlias>-->
	<package name="com.atguigu.mybatis.entities"/>
</typeAliases>

4)typeHandlers标签

用来配置类型处理器

<typeHandlers>
    <typeHanlder handler="配置自定义的类型处理器的全类名"></typeHanlder>
</typeHandlers>

5)plugins标签

用来配置插件,我们可以通过插件来修改MyBatis的一些核心行为。插件通过动态代理机制,可以介入四大对象的任何一个方法的执行

<plugins>
    <plugin interator="配置插件的全类名"></plugin>
</plugins>

6)environments标签

环境配置:MyBatis可以配置多种环境,比如开发测试和生产环境都需要有不同的配置

每个环境都是用一个environment标签进行配置并通过id指定唯一标识符

<environments default="developent">
	<!--开发环境-->
    <environment id="developent">
    	<transactionManager type="JDBC"/>
        <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="online">
        <transactionManager type="JDBC"/>
        <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>

</environments>

7)★databaseIdProvider标签

用来给不同数据库厂商指定别名

<databaseIdProvider>
	<property name="MySql" value="mysql"/>
    <property name="Oracle" value="oracle" />
</databaseIdProvider>

8)★mappers标签

用来注册SQL映射文件(Mapper映射文件)

mapper标签每写一次就需要注册一次,如果是package属性就不需要反复注册

<mappers>
	<mapper resource="com/atguigu/mybatis/dao/Employee.xml"/>
</mappers>
通过子标签mapper注册Mapper映射文件

​ resource属性:指定类路径下的映射文件

​ url属性:指定网络或者磁盘上的映射文件

​ class属性:通过指定接口全类名注册对应的映射文件

​ 使用该属性进行配置有以下要求:

​ 映射文件必须与接口通报同名或者使用注解的方式写sql语句

通过子标签package批量注册Mapper映射文件

​ name属性:指定包名

​ 使用该属性有以下要求:

​ 映射文件必须与接口同包同名或者使用注解的方式写sql语句

<mappers>
	<mapper resource="com.atguigu/mybatis/mapper/EmployeeMapper.xml"/>
    <mapper class="com.aguigu.mybatis.mapper.EmployeeMapper"/>
    <package name="com.atguigu.mybatis.mapper"/>
</mappners>

4. MyBatis映射文件

MyBatis的映射文件是最强大的,与JDBC代码进行对比,省掉了将近95%的代码。

1)MyBatis的CRUD

select

Mapper接口方法

Employee getEmployeeById(Integer id);

Mapper映射文件

<select id="getEmployeeById" resultType="employee" dataBaseId="mysql">
	select id,last_Name lastName,email,salary,dept_id
    from employees
    where id=#{id}
</select>
id属性设置为接口的方法名
resultType属性:设置为方法的返回值的类型的全类名
resultMap属性(二选一):自己映射
flushCache:清理缓存(增删改)默认值false
insert

Mapper接口方法

void insertEmployee(Employee employee);

Mapper映射文件

parameterType属性:指定方法的入参的类型,也可以不指定,MyBatis会自动推断

useGeneratedKeys属性:设置是否获取数据库中生成的主键值,注意:数据库必须支持自增

keyProperty属性:设置获取的主键值赋给POJO的那个属性

<insert>
insert id="insertEmployee" useGeneratedKeys="true" keyProperty="id">
        insert into employees(last_name,email,salary,dept_id)
        values (#{lastName},#{email},#{salary},#{deptId})
</insert>
update

Mapper接口方法

void updateEmployee(Employee employee);

Mapper映射文件

 <!--更新-->
    <update id="updateEmployee">
        update employees set
                             last_name = #{lastName},
                             email = #{email},
                             salary = #{salary},
                             dept_id = #{deptId}
        where id = #{id}
    </update>
delete

Mapper接口方法

Employee deleteEmployeeById(Integer id)

Mapper映射文件

<!--删除-->
    <delete id="deleteEmployeeById">
        delete from employees where id = #{id}
    </delete>

2)参数处理:参数传递

①单个参数

当入参是单个参数,基本类型,包装类型,字符串类型时,MyBatis不做任何处理,填充占位符时,key可以任意指定

如:#{任意指定key}

②多个参数

当入参是多个参数时,MyBatis会封装到一个Map中,此时填充的占位符的key是arg0,arg1,arg2…或者param1,param2…

如:#{arg0}或#{param1}

我们也可以在入参前面添加@Param主键指定key

③传入Map

我们可以将多个参数放在一个Map中传入,此时填充占位符时的key就是Map中指定的Key

如:#{Map中的key}

④入参是POJO

如果传入的多个参数可以封装成POJO对象,那么可以直接传入POJO对象,此时填充占位符的key是POJO的属性名。

如:#{POJO类的属性}

⑤入参为TO(Transfer Object,传输对象)

如果传入的多个参数不可以封装成POJO对象,但是经常使用,可以封装成一个TO

⑥Collection/Array

会被MyBatis封装成一个map传入, Collection对应的key是collection,Array对应的key是array。如果确定是List集合,key还可以是list。

<!--根据员工的姓名和邮箱查询-->
    <select id="getEmployeeByLastNameAndEmail" resultType="employee">
        select id,last_name,email,salary,dept_id
        from employees
        where last_name = #{lastName} and email = #{email}
    </select>
 /*
       测试根据员工姓名和邮箱获取员工对象信息
    */
    @Test
    public void testGetEmployeeByLastNameAndEmail() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            Employee employee = employeeMapper.getEmployeeByLastNameAndEmail("Jack", "roselove@gmail.com");
            System.out.println("employee = " + employee);
        }finally {
            sqlSession.close();
        }
    }

3)select查询的几种情况

查询所有员工返回List

List<Employee> getEmployees();
<!--
        查询所有员工返回List
        resultType属性:如果返回的是List,那么该值就是List中数据的值
    -->
    <select id="getEmployees" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name,email,salary,dept_id
        from employees
    </select>

查询一个员工返回Map,数据库中字段名为key,字段值为value

Map<String,Object> getEmployeeById(Integer id);
<!--查询所有员工返回Map-->
    <select id="getEmployeeById" resultType="map">
        select id,last_name,email,salary,dept_id
        from employees
        where id = #{id}
    </select>

查询所有员工返回Map

@MapKey("last_name")// 需要指定将数据库中的哪个字段指定为key
    Map<String,Object> getEmployeesByMap();
<!--查询所有员工返回Map-->
    <select id="getEmployeesByMap" resultType="map">
        select id,last_name,email,salary,dept_id
        from employees
    </select>
{Mahuateng={last_name=Mahuateng, id=3, salary=10000.0, dept_id=3, email=mahuateng@qq.com}, Jack={last_name=Jack, id=1, salary=52000.0, dept_id=1, email=roselove@gmail.com}}

4)高级结果集映射 (映射主键,映射其他列)

级联属性赋值
<select id="getEmployeeByIdContainsDept" resultMap="myEmp">// 用resultMap需要自己定义高级结果集映射
        SELECT e.*,d.id d_id,d.name d_name
        FROM employees e
                 LEFT JOIN departments d
                           ON e.dept_id = d.id
        WHERE e.id = #{id}
    </select>

自定义高级结果集映射

需要映射employee,所以要引入employee的全类名

column属性:指定数据库中的字段名

property属性:指定POJO的属性名

    <resultMap id="myEmp" type="com.atguigu.mybatis.entities.Employee">
<id column="id" property="id"></id>
         <result column="last_name" property="lastName"></result>
        <result column="email" property="email"></result>
        <result column="salary" property="salary"></result>
        <!--通过级联属性映射部门信息-->
         <result column="d_id" property="dept.id"></result>
        <result column="d_name" property="dept.name"></result>
    </resultMap>
association标签

通过association标签映射部门信息

property属性:要映射属性的属性名

java-type属性:要映射属性的类型

employee中的映射与级联属性相同与dept与级联属性赋值不同

<association property="id" java-type="com.atguigu.mybatis.entities.Department">
    <!--映射主键-->
    <id column="d_id" property="id"></id>
    <!--映射其他列-->
    <result column="d_name" property="name"></result>
</association>
association标签:分步查询

通过分步查询映射部门信息

​ 1.通过员工id查询员工信息

​ 2.根据员工部门id查询部门信息

​ 3.将部门信息设置到员工中(需要查询两条sql,一条sql查员工,一条sql查部门)

通过association标签分步查询映射部门信息

property属性:设置要映射的属性名

select属性:设置要映射哪个接口下的哪个方法映射部门信息(在这里需要调用DepartmentMapper标签下的getDepartmentById方法)

coulumn属性:设置将哪个字段传入到select属性中指定的方法

<association property="dept" select="com.atguigu.mybatis.mapper.DepartmentMapper.getDepartmentById"
             column = "{d_id = dept_id}"></association>
分步查询延迟加载

在mybatis-config的标签中设置

<settings>
        <!--开启驼峰命名法-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--设置加载的数据是按需加载的-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

在association标签中设置fetchType属性

<association property="dept" select="com.atguigu.mybatis.mapper.DepartmentMapper.getDepartmentById"
             column = "dept_id" fetchType="lazy"></association>

在进行分步查询的时候可以查询其他属性

String lastName = employeeMapper.getEmployeeByIdContainsDeptByStep(1).getLastName();
            System.out.println("lastName = " + lastName);
            System.out.println("===================================");
            Double salary = employeeMapper.getEmployeeByIdContainsDeptByStep(3).getSalary();
            System.out.println("salary = " + salary);
lastName = Jack
===================================
DEBUG 04-08 14:51:03,640 ==>  Preparing: select id,last_name,email,salary,dept_id from employees where id = ?  (BaseJdbcLogger.java:137) 
DEBUG 04-08 14:51:03,640 ==> Parameters: 3(Integer)  (BaseJdbcLogger.java:137) 
DEBUG 04-08 14:51:03,642 <==      Total: 1  (BaseJdbcLogger.java:137) 
salary = 10000.0
collection分步查询

5. 动态SQL

动态SQL是Mybatis最强大的特征之一。极大的简化了我们拼装SQL的操作。

if-where

<select id="getEmployeeByConditionIf" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name,email,salary
        from employees where
        <if test="id != null">
            id = #{id} and
        </if>
        <if test="lastName != null &amp;&amp; lastName != &quot;&quot; ">
            last_Name = #{lastName} and
        </if>
        <if test="email != null and email.trim() != '' ">
          email = #{email} and 
        </if>
        <if test="salary != null">
            salary = #{salary} and
        </if>
    </select>

可能会出现的问题

问题一:当值为null的时候,sql语句会出现异常

解决方案一:在最前面添加where 1 = 1(在开发中不常用)
解决方案二:嵌套where标签

问题二:当每个条件后面有and或or的时候,最后一个条件不满足会导致sql语句异常

解决方案一:在整个sql语句后面添加恒等式
解决方案二:使用trim标签

trim标签

prefix属性:添加前缀

prefixOverrides属性:删除前缀

suffix:添加后缀

suffixOverrides:删除后缀

<select id="getEmployeeByConditionIf" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name,email,salary
        from employees
          <trim prefix="where" suffixOverrides="and">
              <if test="id != null">
                  id = #{id} and
              </if>
              <if test="lastName != null &amp;&amp; lastName != &quot;&quot; ">
                  last_Name = #{lastName} and
              </if>
              <if test="email != null and email.trim() != '' ">
                  email = #{email} and
              </if>
              <if test="salary != null">
                  salary = #{salary} and
              </if>
          </trim>
    </select>

choose标签

相当于if…else if… else…

子标签when和otherwise标签需要在choose标签中使用。

when标签只要有一条满足就不再执行

<select id="getEmployeeByConditionChoose" resultType="com.atguigu.mybatis.entities.Employee">
        select id,last_name,email,salary
        from employees where
        <choose>
            <when test="id != null">
                id = #{id}
            </when>
            <when test="lastName!= null">
                last_name = #{lastName}
            </when>
            <when test="email != null">
                email = #{email}
            </when>
            <otherwise>
                salary = #{salary}
            </otherwise>
        </choose>
    </select>

set标签

<!--set标签-->
    <update id="updateEmployeeByConditionSet">
        update employees
        <set>
            <if test="lastName != null">
                last_name = #{lastName},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="salary != null">
                salary = #{salary}
            </if>
        </set>
       where id = #{id}
    </update>

forEach标签

sql标签

SSM整合

Spring与SpringMVC整合**!!!!!标注解@Service@Controller**

  • 在WEB-INF下创建lib文件夹导入jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tcBMi1BM-1618309475135)(C:\Users\可爱的西西里亚\AppData\Roaming\Typora\typora-user-images\image-20210409180604430.png)]

  • 创建controller、service、entities、mapper的包

  • 为spring配置bean文件

  • 引入druid.properties文件

  • 配置自动扫描的包,不扫描Controller

  • 引入外部属性文件,配置数据源属性

  • 配置事务管理器,配置数据源属性

  • 开启事务支持,是tx的

  • 配置web.xml

  • 配置springmvc.xml

  • 创建service

  • 在views中引入list.jsp

  • 创建mapper和Mapper.xml

employees


last_name = #{lastName},


email = #{email},


salary = #{salary}


where id = #{id}


### forEach标签

### sql标签

# SSM整合

## Spring与SpringMVC整合**!!!!!标注解@Service@Controller**

* 在WEB-INF下创建lib文件夹导入jar包

[外链图片转存中...(img-tcBMi1BM-1618309475135)]

* 创建controller、service、entities、mapper的包

* 为spring配置bean文件

* 引入druid.properties文件

* 配置自动扫描的包,不扫描Controller

* 引入外部属性文件,配置数据源属性

* 配置事务管理器,配置数据源属性

* 开启事务支持,是tx的

* 配置web.xml
* 配置springmvc.xml
* 创建service
* 在views中引入list.jsp
* 创建mapper和Mapper.xml





​		



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值