Java_Mybatis

        Mybatis是一款优秀的持久层框架,用户简化JDBC(使用Java语言操作关系型数据库的一套API)开发

使用Mybatis查询所有用户数据:

代码演示:
UserMapper:
@Mapper  //被调用时会通过动态代理自动创建实体类,并放入IOC容器中
public interface UserMapper {

    @Select("select * " +
            "from user")
    public List<User> list();

}
单元测试中使用:
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {

    @Autowired
    public UserMapper userMapper;

    @Test
    public void contextLoads() {
        List<User> list = userMapper.list();
        list.stream().forEach(user -> System.out.println(user));
    }

}

JDBC

JDBC与Mybatis相比:

数据库连接池:

总结:

lombok:

Mybatis日志:

        在application.properties中添加代码

#配置Mybatis的日志信息,并输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

数据库操作

1.通过注解操作数据库

删除操作

根据主键删除:

代码演示:
Mapper类:
@Mapper
public interface EmpMapper {

    @Delete("delete from emp where id = #{id}")
    public void delete(Integer id);

}
单元测试:
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {

    @Autowired
    public EmpMapper empMapper;

    @Test
    public void deleteTest() {
        empMapper.delete(17);
    }

}
注意:

        Mapper中的SQL语句“delete from emp where id = #{id}”,这里我们使用的#占位符,表示大括号中间的id为传递的参数,除了#占位符还有$占位符,但是它们有一些区别

★#占位符和$占位符的区别:

        使用#占位符执行SQL时会将#{...}替换为?,生成预编译SQL,会自动设置参数值,使用时机:参数传递

        使用$占位符执行SQL时会直接将参数拼接到SQL语句中,存在SQL注入问题.

SQL注入:

        SQL注入就是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

        比如username='....' and password='.....',传递给password参数:' or '1' = '1 ,这样会得到username='....' and password='' or '1' = '1',总是为true,这样不知道用户名和密码也可以登录了,使用时机:对表名、列表进行动态设置时使用。

SQL预编译的好处:

        1.性能更高:要想执行SQL语句,要连接上数据库,然后将SQL语句发送到数据库中,再进行SQL语法解析检查,优化SQL,编译SQL,执行SQL。但是在SQL语法解析检查,优化SQL,编译SQL过程中,为了提高效率,它会将优化编译后的SQL缓存起来,比如delete from emp where id = #{id},会缓存为delete from emp where id = ?,这样如果只有后面传递的id参数值改变,只需要在缓存中调用这一句即可,就只需要编译一次

        2.更安全(防止SQL注入),通过参数赋值的方法不会更改原本的SQL语义

新增操作

新增:

代码演示:
Mapper类:
@Mapper
public interface EmpMapper {

    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            "values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);

}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void insertTest() {

        Emp emp = new Emp();
        emp.setUsername("han");
        emp.setName("韩");
        emp.setGender((short) 1);
        emp.setJob((short) 1);
        emp.setEntrydate(LocalDate.of(2010,1,1));
        emp.setDeptId(1);
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp);

    }

}
新增(主键返回):

代码演示:
@Mapper
public interface EmpMapper {

    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            "values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);

}

更新操作:

更新:

代码演示:
Mapper:
@Mapper
public interface EmpMapper {

    @Update("update emp set username= #{username},name= #{name},gender= #{gender},image= #{image}," +
            "job= #{job},entrydate= #{entrydate},dept_id= #{deptId},update_time = #{updateTime} where id = #{id}")
    public void update(Emp emp);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void updateTest() {
        Emp emp = new Emp();
        emp.setId(19);
        emp.setUsername("han1");
        emp.setName("韩1");
        emp.setImage("1.jpg");
        emp.setGender((short) 1);
        emp.setJob((short) 1);
        emp.setEntrydate(LocalDate.of(2010,1,1));
        emp.setDeptId(1);
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.update(emp);

    }

}

查询操作:

根据id查询:
代码演示:
Mapper:
@Mapper
public interface EmpMapper {

    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void getByIdTest() {

        Emp emp = empMapper.getById(19);
        System.out.println(emp);

    }

}
注意:

        这种编写方式得到的结果中有一部分属性值为null

        这是因为mybatis的数据封装特性(如下)。

数据封装:

解决方案一:

        给字段起别名,让别名与实体类属性保持一致

代码演示:

Mapper:

@Mapper
public interface EmpMapper {

    /*
    //与属性名不一致的字段会赋值为null
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);
    */
    //解决方案一:给字段起别名,让别名与实体类属性保持一致
    @Select("select id, username, password, name, gender, image, job, entrydate, " +
            "dept_id deptId, create_time createTime, update_time updateTime" +
            " from emp where id = #{id}")
    public Emp getById(Integer id);

}
解决方案二:

        通过@Results,@Result注解手动映射封装

 代码演示:

Mapper:

@Mapper
public interface EmpMapper {
    /*
    //与属性名不一致的字段会赋值为null
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);
    */
    /*
    //解决方案一:给字段起别名,让别名与实体类属性保持一致
    @Select("select id, username, password, name, gender, image, job, entrydate, " +
            "dept_id deptId, create_time createTime, update_time updateTime" +
            " from emp where id = #{id}")
    public Emp getById(Integer id);
    */
    //解决方案二:通过@Results,@Result注解手动映射封装
    @Results({
            @Result(column = "dept_id",property = "deptId"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime")
    })
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);

}
解决方案三(推荐):

        开启mybatis的驼峰命名自动映射开关

操作步骤:

        只需要在mybatis配置文件application.properties中添加代码

#开启mybatis的驼峰命名自动映射开关(camel)
mybatis.configuration.map-underscore-to-camel-case=true

        这样就可以使用最初的代码也能正确赋值

        但是需要注意:数据库中的字段名要采用下划线命名,Java类中的属性名要采用驼峰命名法

条件查询:

        根据姓名(模糊匹配)、性别、入职日期范围,来查找员工

代码演示:
Mapper:
@Mapper
public interface EmpMapper {

    //条件查询
    @Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
            "entrydate between #{begin} and #{end} order by update_time DESC")
    public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);

}

        这里使用concat函数,是由于#{}会生成预编译SQL,编译后会转换成?,而?存在于单引号中会被认为是字符串,所以使用concat函数,来进行字符串的拼接。

单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void listTest() {

        List<Emp> list = empMapper.getList("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
        System.out.println(list);

    }

}

2.通过XML映射文件操作数据库:

        除了可以使用注解来操作数据库,还可以使用XML映射文件。

代码演示:
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">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper">
    <!--resultType:单条记录所封装的类型-->
    <select id="getList" resultType="com.han.pojo.Emp">
        select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and
                                entrydate between #{begin} and #{end} order by update_time DESC
    </select>

</mapper>
Mapper:
@Mapper
public interface EmpMapper {
    public List<Emp> getList(String name, short gender, LocalDate begin, LocalDate end);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void listTest() {

        List<Emp> list = empMapper.getList("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
        System.out.println(list);

    }

}

3.使用场景

        使用Mybatis的注解,主要是来完成一些简单的增删改查功能/如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

动态SQL:

标签:

1.<if>(<where>、<set>)

查找(<where>):

更新(<set>):

2.<foreach>

        <foreach>一般用于批量操作。

批量操作:
代码演示(批量删除):
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">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper">
    <!--resultType:单条记录所封装的类型-->
    <delete id="deleteByIds">
        delete 
        from emp 
        where id in /*(11,12,13)*/
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

</mapper>
Mapper:
@Mapper
public interface EmpMapper {
    public void deleteByIds(List<Integer> ids);
}
单元测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {

    @Autowired
    private EmpMapper empMapper;

    @Test
    void deleteByIdsTest() {
        List<Integer> list = Arrays.asList(11, 12, 13);
        empMapper.deleteByIds(list);

    }

}

3.<sql>&<include>

代码演示:

        如下面的XML文件代码,其中有一段动态SQL条件查询代码和一段根据id查询代码,它们中有大段的复用代码,如:

        select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
        from emp

使用前代码:
<?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">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper">
    <!--resultType:单条记录所封装的类型-->
    <select id="getById" resultType="com.han.pojo.Emp">
        select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
        from emp
        where id = #{id}
    </select>
    
    <!--resultType:单条记录所封装的类型-->
    <select id="getList" resultType="com.han.pojo.Emp">
        select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
        from emp
        <where>
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>

        <if test="gender != null">
            and gender = #{gender}
        </if>

        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        </where>
        order by update_time DESC
    </select>

</mapper>

        使用<sql>和<include>可以减少代码复用

如下面代码

使用后代码:
<?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">
<!--上面为依赖部分,可在Mybatis中文网->入门 中的SQL部分截取-->
<mapper namespace="com.han.mapper.EmpMapper">

    <sql id="commonSelect">
        select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
        from emp
    </sql>

    <!--resultType:单条记录所封装的类型-->
    <select id="getById" resultType="com.han.pojo.Emp">
        <include refid="commonSelect"/>
        where id = #{id}
    </select>
    
    <!--resultType:单条记录所封装的类型-->
    <select id="getList" resultType="com.han.pojo.Emp">
        <include refid="commonSelect"/>
        <where>
        <if test="name != null">
            name like concat('%', #{name}, '%')
        </if>

        <if test="gender != null">
            and gender = #{gender}
        </if>

        <if test="begin != null and end != null">
            and entrydate between #{begin} and #{end}
        </if>
        </where>
        order by update_time DESC
    </select>


</mapper>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/669484.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文了解JVM面试篇(上)

Java内存区域 1、如何解释 Java 堆空间及 GC? 当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建 堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一 个进程,回收无效对象的内存用于将来的分配。 2、JVM 的主要组成…

JVM学习-详解类加载器(一)

类加载器 类加载器是JVM执行类加载机制的前提 ClassLoader的作用 ClassLoader是Java的核心组件&#xff0c;所有的Class都是由ClassLoader进行加载的&#xff0c;ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部&#xff0c;转换为一个与目标类型对应的ja…

什么是TLAB?

这个得从内存申请说起。 一般而言生成对象需要向堆中的新生代申请内存空间&#xff0c;而堆又是全局共享的&#xff0c;像新生代内存又是规整的&#xff0c;是通过一个指针来划分的。 内存是紧凑的&#xff0c;新对象创建指针就右移对象大小size即可&#xff0c;这叫指针加法…

Linux 的权限

目录 Linux 的用户 root 用户 和 普通用户 如何新建普通用户&#xff1f; 如何切换用户&#xff1f; 一开始是以 root 用户登录&#xff1a; 一开始以普通用户登录&#xff1a; 如何删除用户&#xff1f; Linux文件权限 什么是读权限&#xff08; r &#xff09;&#…

数据结构学习笔记

1. 数组 (Array) 定义 数组是一种线性数据结构&#xff0c;用于存储固定大小的相同类型元素集合。每个元素都有一个索引&#xff0c;用于快速访问。 特点 优点&#xff1a;访问速度快&#xff0c;通过索引直接访问O(1)时间复杂度。缺点&#xff1a;大小固定&#xff0c;插入…

Unity 自定义房间布局系统 设计与实现一个灵活的房间放置系统 ——自定义房间区域功能

自定义房间区域功能 效果&#xff1a; 功能&#xff1a; 能够自定义房间的大小一键生成放置区域可控的放置网格点当物体放置到区域内可自动吸附物体是否可放置&#xff0c;放置时如果与其他物体交叉则不可放置&#xff08;纯算法计算&#xff09;管理房间内的物体&#xff0c…

MySQL(二)-基础操作

一、约束 有时候&#xff0c;数据库中数据是有约束的&#xff0c;比如 性别列&#xff0c;你不能填一些奇奇怪怪的数据~ 如果靠人为的来对数据进行检索约束的话&#xff0c;肯定是不行的&#xff0c;人肯定会犯错~因此就需要让计算机对插入的数据进行约束要求&#xff01; 约…

下载HF AutoTrain 模型的配置文件

下载HF AutoTrain 模型的配置文件 一.在huggingface上创建AutoTrain项目二.通过HF用户名和autotrain项目名,拼接以下url,下载模型列表(json格式)到指定目录三.解析上面的json文件、去重、批量下载模型配置文件(权重以外的文件) 一.在huggingface上创建AutoTrain项目 二.通过HF用…

电脑没电关机,wsl和docker又挂了,附解决过程

如题&#xff0c;开了个会没带笔记本电源&#xff0c;点啊弄关机后docker打不开&#xff0c;我以为是docker坏了&#xff0c;结果docker报错&#xff1a; An unexpected error occurred while executing a WSL command. Either shut down WSL down with wsl --shutdown, and/or…

植被变化趋势线性回归以及可视化

目录 植被变化线性回归ee.Reducer.linearFit().reduce()案例:天水市2004-2023年EVI线性回归趋势在该图中,使用了从红色到蓝色的渐变来表示负趋势到正趋势。红色代表在某段时间中,植被覆盖减少,绿色表示持平,蓝色表示植被覆盖增加。 植被变化线性回归 该部分参考Google…

Java(十一)---String类型

文章目录 前言1.String类的重要性2.常用方法2.1.字符串的创建2.2.字符串的比较2.2.1.比较是否引用同一个对象2.2.2.boolean equals(Object anObject) 方法&#xff1a;2.2.3.int CompareTo(String s)2.2.4.int compareToIgnoreCase(String str) 方法&#xff1a; 2.3.字符串的查…

单调栈原理+练习

首先用一道题引出单调栈 码蹄集 (matiji.net) 首先画一个图演示山的情况&#xff1a; 最暴力的做法自然是O(n方)的双循环遍历&#xff0c;这么做的思想是求出当前山右侧有多少座比它小的山&#xff0c;遇见第一个高度大于等于它的就停止。 但是对于我们所求的答案数&#xff…

能不能接受这些坑?买电车前一定要看

图片来源&#xff1a;汽车之家 文 | Auto芯球 作者 | 雷慢 刚有个朋友告诉我&#xff0c;买了电车后感觉被骗了&#xff0c; 很多“坑”都是他买车后才知道的。 不提前研究&#xff0c;不做功课&#xff0c;放着我这个老司机不请教&#xff0c; 这个大冤种他不当谁当&…

C# WinForm —— 25 ProgressBar 介绍与使用

1. 简介 用于显示某个操作的进度 2. 常用属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 pbar 开头ContextMenuStrip右键菜单Enabled控件是否可用ForeColor用于显示进度的颜色MarqueeAnimationSpeed进度条动画更新的速度&#xff0c;以毫秒为单位M…

【Python】解决Python错误报错:IndexError: tuple index out of range

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

什么是PLAB?

接上文PLAB---》 可以看到和TLAB很像&#xff0c;PLAB即 Promotion Local Allocation Buffers。用在年轻代对象晋升到老年代时。 在多线程并行执行YGC时&#xff0c;可能有很多对象需要晋升到老年代&#xff0c;此时老年代的指针就"热"起来了&#xff0c;于是搞了个…

新游启航 失落的方舟台服注册指南 一文教会你方舟台服注册

新游启航&#xff01;失落的方舟台服注册指南&#xff01;一文教会你方舟台服注册 失落的方舟作为本月最受期待游戏之一&#xff0c;在上线之际许多玩家已经有点急不可待了。这款游戏是由开发商Smile gate开发的一款MMORPG类型游戏&#xff0c;这款游戏的基本玩法与其他MMORPG…

44-1 waf绕过 - WAF的分类

一、云 WAF 通常包含在 CDN 中的 WAF。在配置云 WAF 时&#xff0c;DNS 需要解析到 CDN 的 IP 上。请求 URL 时&#xff0c;数据包会先经过云 WAF 进行检测&#xff0c;如果通过检测&#xff0c;再将数据包流向主机。 二、硬件IPS/IDS防护、硬件WAF 硬件IPS/IDS防护&#xff…

归并排序C++代码详解,思路流程+代码注释,带你完全学会归并排序

归并排序 归并排序是一种经典的排序算法&#xff0c;属于分治算法的一种。其核心思想是将一个大问题分解成若干个较小的子问题来解决&#xff0c;然后根据子问题的解构建原问题的解。在排序问题中&#xff0c;归并排序将数组分成两半&#xff0c;分别对这两半进行排序&#xf…

0基础认识C语言(理论+实操3)

所有籍籍无名的日子里 我从未看轻自己半分 小伙伴们&#xff0c;一起开始我们今天的话题吧 一、算法操作符 1.双目操作符 为何叫双目操作符呢&#xff1f;其实是因为我们进行加减乘除的时候&#xff0c;至少得需要两个数字进行这些运算&#xff0c;而这个数字就被称为操作数…