Mybatis

Mybatis

IDEA配置环境

https://blog.csdn.net/qq_16804847/article/details/120409429?spm=1001.2014.3001.5502

pom.xml

<!--    热部署    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--引入插件lombok 自动的set/get/构造方法插件  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--mybatis依赖包-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--jdbc依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

热部署

配置自动编译
在这里插入图片描述

让热部署有效,快捷键: ctrl + alt + shift + /
在这里插入图片描述

勾选自动重启
在这里插入图片描述

插件Lombok

package com.jt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * 实体对象要求:
 *      1.类名一般与表名关联
 *      2.属性名称一般与字段关联
 *      3.pojo中的属性类型必须为引用类型(包装类型)
 *      4.实体对象必须有get/set方法
 *      5.一般实体对象需要实现序列化接口(规则)
 *          原因: 数据可能跨平台(跨服务器)传输,必须序列化
 */
@Data  //动态生成get/set/toString/equals等方法
@Accessors(chain = true) //开启链式加载 重写set方法
@NoArgsConstructor  //无参构造
@AllArgsConstructor //有参构造
public class DemoUser implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;

    //this 运行期有效 代表当前对象
    /*public DemoUser setId(Integer id){
        this.id = id;
        return this;
    }*/

    //方法测试
    public void add(){
        DemoUser user = new DemoUser();
        user.setId(100)
            .setName("aaaa")
            .setAge(18)
            .setSex("女");
    }

}

Mybatis案例

编辑mybatis-config.xml

核心配置文件的顺序

The content of element type "configuration" must match "
(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".

自动驼峰映射,resultMap中不需要再写 < result column=“dept_name” property=“deptName” />

<?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="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--  配置别名  -->
    <typeAliases>
<!--        <typeAlias type="com.jt.pojo.DemoUser" alias="DemoUser"/>-->
        <package name="com.jt.pojo"/>
    </typeAliases>

    <!--环境配置标签-->
    <environments default="development">

        <!--编辑开发环境-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--Mybatis加载Mapper映射文件-->
    <mappers>
        <mapper resource="mybatis/mappers/DemoUserMapper.xml"/>
        <mapper resource="mybatis/mappers/DeptMapper.xml"/>
        <mapper resource="mybatis/mappers/EmpMapper.xml"/>
    </mappers>
</configuration>

构建持久层接口

/**
 * 说明:
 *      1.根据面向接口开发的思想需要定义一个Mapper接口
 *      2.在接口中可以写接口方法, 谁用谁去实现!!!
 */
public interface DemoUserMapper {

    //查询所有的表数据
    public List<DemoUser> findAll();

}

构建mapper接口的实现类的xml配置文件

DemoUserMapper.xml,sql简化,常规CURD操作
<?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是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.DemoUserMapper">

    <!-- 简化sql标签 -->
    <sql id="demo_dept_sql">
        select id,name,age,sex from demo_user
    </sql>
    <!--id 表示接口方法
        resultType 返回值结果类型
    -->
    <select id="findAll" resultType="DemoUser">
        <include refid="demo_dept_sql" />
    </select>

	<!-- parameterType属性可以不写 -->
	<insert id="saveDemoUser" parameterType="com.jt.pojo.DemoUser">
        insert into demo_user(id,name,age,sex) values (null,#{name},#{age},#{sex})
    </insert>

    <update id="updateDemoUser" parameterType="com.jt.pojo.DemoUser">
        update demo_user set name=#{name},age=#{age},sex=#{sex} where id=#{id}
    </update>

    <delete id="deleteDemoUser" parameterType="Integer">
        delete from demo_user where id=#{id}
    </delete>

</mapper>
DeptMapper.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">

<!--namespace是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.DeptMapper">

	<!--
        关于一对多 数据封装说明:
            1.collection: 封装集合的固定写法.
                property:   指定属性
                ofType:     封装List集合的泛型对象
            2.如果开启驼峰映射规则,可以简化赋值过程
            3.autoMapping="true" 自动实现映射
            4.一般最好保留主键,为后续扩展提供方便.
    -->
    <select id="findAll" resultMap="deptRM">
        select id,name,age,dept.dept_id,dept_name from dept
        left join emp on emp.dept_id = dept.dept_id
    </select>
    <!--  自定义映射关系  -->
    <resultMap id="deptRM" type="Dept" autoMapping="true">
<!--        开启驼峰命名规则-->
        <id column="dept_id" property="deptId"/>
<!--        <result column="dept_name" property="deptName"/>-->
        <collection property="empList" ofType="Emp" autoMapping="true">
            <id column="id" property="id"/>
        </collection>
    </resultMap>

</mapper>
EmpMapper.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">

<!--namespace是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.EmpMapper">

<!--
        规则:
            1.如果映射的字段与对象的属性一致,则可以省略不写.
            2.最好保留主键的字段信息.
            3.如果需要封装单个对象则使用association标签
                3.1 property 代表封装对象的属性
                3.2 javaType 指定属性的类型 注意路径
            4.如果遇到关联封装,必须全部配置映射关系. 如果属性与字段名称一致
              则可以使用autoMapping="true"实现自动映射
    -->
<!-- 直接用where或left join来进行多表联查 -->
    <select id="findAll" resultMap="empRM">
        select id,name,age,dept.dept_id,dept_name from emp,dept
        where emp.dept_id = dept.dept_id
    </select>
    <!--  自定义映射关系  -->
    <resultMap id="empRM" type="Emp" autoMapping="true">
        <id column="id" property="id"/>
        <!-- autoMapping="true"属性可以自动映射字段名和属性名 -->
<!--        <result column="name" property="name"/>-->
<!--        <result column="age" property="age"/>-->
        <association property="dept" javaType="Dept"><!-- association可以注入实体对象 -->
            <id column="dept_id" property="deptId"/>
            <result column="dept_name" property="deptName"/>
        </association>
    </resultMap>
    
<!-- 将两个单表查询的select连接起来查询,where dept_id = #{deptId} -->
    <select id="findAllWhere" resultMap="empRM2">
        select id,name,age,dept_id from emp
    </select>
    <resultMap id="empRM2" type="Emp" autoMapping="true">
        <id column="id" property="id"/>
        <association property="dept" javaType="Dept" column="dept_id" select="findDept"/>
    </resultMap>
    <select id="findDept" resultMap="deptRM">
        select dept_id,dept_name from dept where dept_id = #{deptId}
    </select>
    <resultMap id="deptRM" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </resultMap>


</mapper>

Mybatis实现数据查询

@Test
public void demo() throws IOException {
	//指定配置文件地址
    String resource = "mybatis/mybatis-config.xml";
    //通过IO流 加载指定的配置文件
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //动态生成SqlSessionFactory
  	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        
	//获取SqlSession  类比 数据库链接
	SqlSession sqlSession = sqlSessionFactory.openSession();//openSession(true)自动提交事务到数据库
	//获取Mapper接口
	DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        
	//获取数据
	List<DemoUser> userList = demoUserMapper.findAll();
	System.out.println(userList);
	//关闭链接
	sqlSession.close();
}

在这里插入图片描述
简化操作

public class TestMybatis {

      //定义公共的属性
      private SqlSessionFactory sqlSessionFactory;
      /**
       * mybatis的核心 SqlSessionFacotry对象
       * @BeforeEach: 测试API中的注解 在执行@Test注解方法时,会提前执行!!!
       */
      @BeforeEach
      public void init() throws IOException {
            //1.指定资源文件
            String resource = "mybatis/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory =
                    new SqlSessionFactoryBuilder().build(inputStream);
      }
      
      @Test
      public void testMybatis01(){
            SqlSession sqlSession = sqlSessionFactory.openSession();
            DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
            List<DemoUser> list = demoUserMapper.findAll();
            System.out.println(list);
            sqlSession.close();
      }
}

#号和$符用法

mybatis默认支持单值传参.如果遇到多值,需要将多值转化为单值.
1.利用POJO对象封装
2.利用万能的Map集合
3.如果参数一定使用多值操作,则使用@Param(“sex”) String sex

如果参数采用对象封装,则可以使用#{属性}取值.
如果参数有多个,可以封装为map实现参数的传递. 可以利用#{key}获取数据
也可以使用@Param将多个参数封装为map, 利用#{key}的方式获取数据

使用#{} 获取数据时,默认有预编译的效果.防止sql注入攻击.
mybatis使用#{}获取数据时,默认为数据添加一对""号.
当以字段名称为参数时,一般使用${},但是这样的sql慎用. 可能出现sql注入攻击问题.

Mybatis集合用法

/**
     * 例如: 删除id=232/233/234的数据?
     *  Sql: delete from demo_user where id in (232,233,234)
     * 规则: 如果遇到相同的多个数据,则一般采用集合的方式封装数据.
     * 封装方式:
     *      1. array
     *      2. list
     *      3. map<List>
     */
    @Test
    public void testDeleteIds(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        //将数据封装为数组,也可以为List集合,Map集合
        int[] ids = {232,233,234};
        demoUserMapper.deleteIds(ids);
        System.out.println("删除操作成功!!!");
    }

接口
在这里插入图片描述

<!--
        需求: 批量删除多个数据
        难点: 如果使用#{集合}获取的是集合对象的整体.删除无效.
        思路: 将数组拆分为单个数据. 可以通过遍历的方式操作
        语法: mybatis为了参数取值方便,特意封装了遍历的标签 foreach
        关于标签参数说明:
            <foreach collection=""></foreach>
            1.如果传递的参数是数组,     则collection="array"
            2.如果传递的参数是list集合, 则collection="list"
            3.如果传递的参数是Map集合,  则collection="map中的key"

        标签属性说明:
            1.collection 集合的名称
            2.item 每次遍历的数据的形参变量
            3.open 循环的开始标签
            4.close 循环的结束标签
            5.index 循环遍历下标 一般不用
            6.separator 循环遍历的分割符
    -->
    <delete id="deleteIds">
        delete from demo_user where id in (
            <foreach collection="array" item="id" separator=",">
                #{id}
            </foreach>
        )
    </delete>

动态Sql

IF-WHERE用法
<!--动态Sql案例
        思路: 如果数据不为null,mybatis才会当做条件
        if标签说明:
            test: 判断的条件 直接写属性即可
        where标签: 去除条件中多余的 and 或者 or的
        说明: if和 where 几乎一起出现.
    -->
    <select id="findWhere" resultType="DemoUser">
        select id,name,age,sex from demo_user
            <where>
                <if test="name != null">name = #{name}</if>
                <if test="age !=null"> and age=#{age}</if>
                <if test="sex !=null"> and sex=#{sex}</if>
            </where>
    </select>
动态Sql-SET标签
<!--
        规则: 根据对象中不为null的属性当做set条件
        set标签说明: 去除set条件中多余的 ,号
    -->
    <update id="updateUser">
        update demo_user
            <set>
                <if test="name !=null">name = #{name},</if>
                <if test="age !=null">age = #{age},</if>
                <if test="sex !=null">sex = #{sex}</if>
            </set>
            where
                id = #{id}
    </update>
动态Sql-choose when otherwise
<!--
        需求: 如果不想将全部的条件当做if的判断.则mybatis提供了分支结构 switch
        语法说明:
              choose:代表分支结构,只有一个条件有效.
              when: 指定判断的条件 和if类似.
              otherwise: 如果上述的条件都不满足时,该行代码有效.
    -->
    <select id="selectChoose" resultType="DemoUser">
        select * from demo_user
        where
            <choose>
                <when test="name !=null">name = #{name}</when>
                <otherwise>sex = #{sex}</otherwise>
            </choose>
    </select>

resultType与resultMap用法

resultType说明:
当结果集中的字段名称,如果与属性的名称一致时,才会实现自动的数据封装
resultMap说明:
当结果集中的字段名称,与对象中的属性不一致时,可以使用resultMap实现自定义的封装.

Mybatis中的缓存机制

一级缓存

概念说明: Mybatis默认开启一级缓存, 一级缓存可以在同一个SqlSession对象中查询相同的数据,可以实现数据的共享(缓存操作).

/**
     * Mybatis一级缓存: 默认开启
     *      规则: 同一个SqlSession内部有效.
     */
    @Test
    public void cache1(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        List<DemoUser> list1 = demoUserMapper.findAll();
        List<DemoUser> list2 =demoUserMapper.findAll();
        List<DemoUser> list3 =demoUserMapper.findAll();
        System.out.println(list1 == list2);
        sqlSession.close();
    }
二级缓存

说明: 二级缓存mybatis中默认也是开启的.但是需要手动标识. 二级缓存可以在同一个SqlSessionFactory内部有效.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
     * 二级缓存说明:
     *     sqlSession查询数据之后,会将缓存信息保存到一级缓存中.但是不会立即将
     *     缓存交给二级缓存保管.如果需要使用二级缓存,则必须将sqlSession业务逻辑执行成功之后关闭.
     */
    @Test
    public void cache2(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper = sqlSession.getMapper(DemoUserMapper.class);
        demoUserMapper.findAll();
        //关闭一级缓存
        sqlSession.close();

        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        DemoUserMapper demoUserMapper2 = sqlSession2.getMapper(DemoUserMapper.class);
        demoUserMapper2.findAll();
        sqlSession2.close();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值