MyBatis 查询数据库

一. MyBatis 框架的搭建

本篇所用sql 表:

drop table if exists  userinfo;
create table userinfo(id int primary key auto_increment,username varchar(100) not null,password varchar(32) not null,photo varchar(500) default '',createtime timestamp default current_timestamp,updatetime timestamp default current_timestamp,`state` int default 1
) default charset 'utf8mb4';

添加 MyBatis 框架

设置  MyBatis 配置

(i) 设置数据库的连接信息

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/blog?characterEncoding=utf8
spring.datasource.name=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

(ii) 设置MyBatis配置信息

# 设置 MyBatis XML 存放路径和命名规则
mybatis.mapper-locations=classpath:mybatis/*Mapper.xml#设置 MyBatis 执行时打印 SQL(可选配置项)
mybatis.configuration.log_impl=org.apache.ibatis.logging.stdout.StdOutImpl
#上述MyBatis 打印设置默认是debug级别,因此需要在demo路径下的日志级别设置为debug,否则上述配置是没用的
logging.level.com.example.demo=debugout.StdOutImpl

二. 根据 MyBatis 完成数据库的操作

1. 定义接口

@Mapper
public interface UserMapper {List<Userinfo> getAll();
}

2. 生成数据库表对应的类对象 

@Data
public class Userinfo {private int id;private String username;private String password;private String photo;private LocalDateTime createtime;private LocalDateTime updatetime;private int state;
}

类中的属性和数据库表中的字段名不一致时,那么查询结果为null, 解决方案:

将类中的属性和表中的字段名保持一致

在 SQL 语句中使用 as 将字段名进行重命名

<!--假设我的数据库中的字段名为username,类中的属性名为name-->
select username as name from userinfo where id=#{id}

定义一个 resultMap ,将属性名和字段名进行手动映射。

<!--    type: 要映射的实体类--><resultMap id="MyMap" type="com.example.demo.model.Userinfo">
<!--        id标签中写的是主键的字段,column 对应的是数据库中的字段, property 对应的是类中的属性名--><id column="id" property="id"></id>
<!--        result 标签中是普通的字段与属性--><result column="username" property="name"></result><result column="password" property="password"></result></resultMap><!--    <select id="getUsrByID" resultType="com.example.demo.model.Userinfo">--><select id="getUsrByID" resultMap="com.example.demo.dao.UserMapper.MyMap">select * from userinfo where id=#{id}</select>

MyBatis Plus : @TableField("数据库字段名")

3. 使用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.example.demo.dao.UserMapper">
<!--    id 为方法名,resultType是返回类型,resultType使用全路径--><select id="getAll" resultType="com.example.demo.model.Userinfo">select * from userinfo;</select>
</mapper>

4. 生成测试类验证 

//告诉当前测试程序,目前项目时运行在Spring Boot 容器中的
@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid getAll() {List<Userinfo> list=userMapper.getAll();System.out.println(list);}
}

三. 增删查改操作

3.1 查询操作

    //参数名以注解中的为准Userinfo getUsrByID(@Param("id")Integer uid);<select id="getUsrByID" resultType="com.example.demo.model.Userinfo"><!--select * from userinfo where id=${id}-->select * from userinfo where id=#{id}</select>

3.2 SQL注入

    //SQL注入Userinfo getUser(@Param("username") String name,@Param("password")String password);<select id="getUser" resultType="com.example.demo.model.Userinfo">select * from userinfo where username='${username}' and password='${password}'</select>@Testvoid getUser() {String username="admin";String password="'or 1='1";Userinfo user=userMapper.getUser(username,password);System.out.println(user);}//替换后语句:
//select * from userinfo where username='admin' and password=''or 1='1'

#{} 和 ${} 的区别:

• ${} 是直接替换; #{} 是预执行.

• ${} 是不安全的,存在SQL注入;而#{} 是安全的,不存在SQL注入

• 如果是非数值类型,${} 替换需要手动添加 '' ,而#{}不需要

从上述的事例可以看出${}可以实现的功能 #{}都能实现,并且${}还有SQL的问题,那${}存在的意义是什么?

    //使用${}排序List<Userinfo> getByOrder(@Param("myorder")String myorder);<select id="getByOrder" resultType="com.example.demo.model.Userinfo"><!--        select * from userinfo order by id #{myorder}-->select * from userinfo order by id ${myorder}
</select>@Testvoid getByOrder() {List<Userinfo> list=userMapper.getByOrder("desc");System.out.println(list);}

${} 适用场景: 当业务需要传递 SQL 命令时, 只能使用 ${}, 不能使用 #{}。(例如需要排序时)

${} 注意事项:如果要使用${},那么传递的参数一定要能够被穷举,否则是不能使用的。(引起 SQL 注入问题

3.3 删除操作

    //删除操作int delete(@Param("id")Integer id);<delete id="delete">delete from userinfo where id=#{id}</delete>//操作不影响数据库@Transactional@Testvoid delete() {int row=userMapper.delete(1);System.out.println("受影响的行数: "+row);}

3.4 修改操作

    //更行操作int update(Userinfo userinfo);<update id="update">update userinfo set username=#{username} where id=#{id}</update>@Testvoid update() {Userinfo userinfo=new Userinfo();userinfo.setId(2);userinfo.setUsername("lisi");int n=userMapper.update(userinfo);}

3.5 插入操作

    //插入操作int add(Userinfo userinfo);<insert id="add">insert into userinfo(username,password) values(#{username},#{password})</insert>@Testvoid add() {Userinfo userinfo=new Userinfo();userinfo.setUsername("王五");userinfo.setPassword("23456");int num=userMapper.add(userinfo);System.out.println("受影响的行数: "+num);}

3.6 特殊的添加: 返回自增的 id

默认情况下返回的是受影响的行号,如果想要返回自增id,具体实现如下

    //返回自增idint insert (Userinfo userinfo);<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id">insert into userinfo(username,password) values(#{username},#{password})</insert>@Testvoid insert() {Userinfo userinfo=new Userinfo();userinfo.setUsername("zhangsan");userinfo.setPassword("23456");int num=userMapper.insert(userinfo);System.out.println("受影响的行数: "+num +" | ID: "+userinfo.getId());}

• useGeneratedKeys:使MyBatis 使用JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键

• keyColumn:数据库自增主键字段名

• keyProperty:数据库自增的id 在类对象中对应的属性名,会将数据库中的自增主键的值赋值给该属性

3.7 like 查询

List<Userinfo> selectLike(@Param("username")String username);<select id="selectLike" resultType="com.example.demo.model.Userinfo">select * from userinfo where username like concat('%',#{username},'%')</select>@Testvoid selectLike() {String usename="san";List<Userinfo> userinfo=userMapper.selectLike(usename);System.out.println(userinfo);}

这里不使用${}的原因是因为传入的参数不能穷举。除了使用concat函数,还可以将参数拼接后在进行传入。例如:传入的是"san",可以在业务层先拼接为"%san%",再进行传参。

3.8 多表查询

3.8.1 一对一

@Data
public class Articleinfo {int id;String title;String content;LocalDateTime createtime;LocalDateTime updatetime;int uid;int rcount;int state;//用户表关联字段private String username;
}
//使用注解替代xml来实现SQL   @Select("select a.*, u.username from articleinfo a left join userinfo u on u.id=a.uid")List<Articleinfo> select();@AutowiredArticleMapper articleMapper;@Testvoid select() {List<Articleinfo> list=articleMapper.select();System.out.println(list);}

3.8.2  一对多 

    @Select("select * from userinfo where id=#{id}")Userinfo getUserById(@Param("id") Integer id);@Select("select * from Articleinfo where uid=#{uid}")List<Articleinfo> selectByUid(@Param("uid")Integer id);@Testvoid selectMuch() throws ExecutionException, InterruptedException {ThreadPoolExecutor pool=new ThreadPoolExecutor(2, 2, 10,TimeUnit.SECONDS,new LinkedBlockingDeque(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());Callable<Userinfo> callable=new Callable<Userinfo>() {@Overridepublic Userinfo call(){return userMapper.getUserById(4);}};Callable<List<Articleinfo>> callable1=new Callable<List<Articleinfo>>() {@Overridepublic List<Articleinfo> call() throws Exception {return articleMapper.selectByUid(4);}};FutureTask<Userinfo> futureTask= (FutureTask<Userinfo>) pool.submit(callable);FutureTask<List<Articleinfo>> futureTask1= (FutureTask<List<Articleinfo>>) pool.submit(callable1);
//        while (pool.getTaskCount()!= pool.getCompletedTaskCount());Userinfo userinfo=futureTask.get();List<Articleinfo> list=futureTask1.get();userinfo.setList(list);System.out.println(userinfo);}

四. 复杂情况: 动态SQL使用

在某些场景,如再添加用户的时候不确定某些字段是否会传递,为了不使数据库中对应的值为null,就需要用到下面的标签.

4.1 <if> 标签

int add2(Userinfo userinfo);<insert id="add2">insert into userinfo(username,password<if test="photo!=null">,photo</if>)values(#{username},#{password}<if test="photo!=null">,#{photo}</if>)</insert>@Testvoid add2() {Userinfo userinfo=new Userinfo();userinfo.setUsername("张三");userinfo.setPassword("123");
//        userinfo.setPhoto("");int result=userMapper.add2(userinfo);System.out.println("成功操作: "+result);}

4.2 <trim> 标签

<if>标签,只适用于一个非必填的字段,如果所有要插入的属性都是非必填的属性,就考虑使用<trim>标签结合<if> 标签,对多个字段都采取动态生成的方式.

<trim>标签的属性:

• prefix: 表示整个语句块,以prefix 的值作为前缀

• suffix: 表示整个语句块,以suffix 的值作为后缀

• prefixOverrides: 表示整个语句块要去掉的前缀

• suffixOverrides: 表示整个语句块要去掉的后缀

    <insert id="add3">insert into userinfo<trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null">username,</if><if test="password!=null">password,</if><if test="photo!=null">photo,</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null">#{username},</if><if test="password!=null">#{password},</if><if test="photo!=null">#{photo},</if></trim></insert>

 

4.3 <where> 标签

<where>标签会动态的生成where

    List<Userinfo> selectByWhere(Userinfo userinfo);<select id="selectByWhere" resultType="com.example.demo.model.Userinfo">select * from userinfo<where><if test="id>0">id=#{id}</if><if test="username!=null">and username=#{username}</if><if test="password!=null">and password=#{password}</if><if test="photo!=null">and photo=#{photo}</if></where></select>@Testvoid selectByWhere() {Userinfo userinfo=new Userinfo();
//        userinfo.setId(2);userinfo.setUsername("lisi");
//        userinfo.setPassword("234567");
//        userinfo.setPhoto("cat.png");List<Userinfo> list=userMapper.selectByWhere(userinfo);System.out.println(list);}

4.4 <set> 标签

int updateByID(Userinfo userinfo);<update id="updateByID">update userinfo<set><if test="username!=null">username=#{username},</if><if test="password!=null">password=#{password},</if><if test="photo!=null">photo=#{photo}</if></set>where id=#{id}</update>@Testvoid updateByID() {Userinfo userinfo=new Userinfo();userinfo.setId(12);userinfo.setUsername("张三");userinfo.setPassword("123");userinfo.setPhoto("cat.png");int result=userMapper.updateByID(userinfo);System.out.println("成功操作: "+result);}

4.5 <foreach> 标签

<foreach>标签属性:

• collection: 绑定方法参数中的集合,如List,Set,Map或数组对象(值和传入的参数名相同)

• item: 遍历时的每一个对象

• open: 语句块开头的字符串

• close: 语句块结束的字符串

• separator: 每次遍历之间间隔的字符串

List<Userinfo> selectByIds(List<Integer> IDs);<select id="selectByIds" resultType="com.example.demo.model.Userinfo">select * from userinfo where id in<foreach collection="IDs" item="id" open="(" close=")" separator=",">#{id}</foreach></select>@Testvoid selectByIds() {List<Integer> list=new ArrayList<>() {{add(2);add(12);}};List<Userinfo> list1=userMapper.selectByIds(list);System.out.println(list1);}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

教你用通义千问只要五步让千年的兵马俑跳上现代的科目三?

教你用五步让千年的兵马俑跳上现代的舞蹈科目三&#xff1f; 上面这个“科目三”的视频&#xff0c;只用了一张我上月去西安拍的兵马俑照片生成的。 使用通义千问&#xff0c;只要5步就能它舞动起来&#xff0c;跳上现在流行的“科目三”舞蹈。 全民舞王 第1步 打开通义千问…

【Spring实战】29 @Value 注解

文章目录 1. 定义2. 好处3. 示例1&#xff09;注入基本类型2&#xff09;注入集合类型3&#xff09;使用默认值4&#xff09;注入整数和其他类型 总结 在实际的应用中&#xff0c;我们经常需要从外部配置文件或其他配置源中获取参数值。Spring 框架提供了 Value 注解&#xff0…

《DAMA数据管理知识体系指南》05—第5章 数据建模和设计 知识点记录

第5章 数据建模和设计 5.1 引言 1.数据建模概要&#xff1a; 1&#xff09;本章将描述数据模型的用途、数据建模中的基本概念和常用词汇以及数据建模的目标和原则。本章将使用一组与教育相关的数据作为案例来说明用各种数据建模的方法&#xff0c;并介绍它们之间的差异。 2&a…

如何用Mac工具制作“苹果高管形象照”

大伙儿最近有没有刷到“苹果高管形象照”风格&#xff0c;详细说来就是&#xff1a; 以苹果官网管理层简介页面中&#xff0c;各位高管形象照为模型&#xff0c;佐以磨皮、美白、高光等修图术&#xff0c;打造的看上去既有事业又有时间有氧的证件照&#xff0c;又称“苹…

OpenCV-25sobel算子(索贝尔算子)

前面所提到的滤波都是用于降噪的&#xff0c;去掉噪声&#xff0c;而算子是用来找边界&#xff0c;来识别图像的边缘。 一、概念 边缘是像素值发生跃迁的值&#xff0c;是图像的显著特点之一&#xff0c;在图像特征提取&#xff0c;对象检测&#xff0c;模式识别等方面都有重…

Vue3响应式系统(一)

一、副作用函数。 副作用函数指的是会产生副作用的函数。例如&#xff1a;effect函数会直接或间接影响其他函数的执行&#xff0c;这时我们便说effect函数产生了副作用。 function effect(){document.body.innerText hello vue3 } 再例如&#xff1a; //全局变量let val 2f…

力扣54. 螺旋矩阵

模拟 思路&#xff1a; 转向表示&#xff1a;使用行下标和列下标变化&#xff1b; 比如向上&#xff1a;行下标 - 1&#xff0c; 列下标&#xff0c;即 {-1, 0}同理向下 {1, 0}{0, 1} 表示向右{0, -1} 表示向左螺旋方向为&#xff1a;向右、向下、向左、向上&#xff0c;周期变…

《微信小程序开发从入门到实战》学习八十三

6.13 视频API 使用视频API可以对用户手机设备中的视频进行一些操作。如果希望播放视频内容&#xff0c;需要使用小程序中的video组件。 6.13.1 保存视频API 使用wx.saveVideoToPhotosAlbum接口可将视频保存到手机相册&#xff0c;支持MP4视频格式。该接口用前需用户授权scop…

RESTfulAPI和webservice 到底有啥区别

RESTful API和Web Service在多个方面存在显著的区别。 首先&#xff0c;从定义上看&#xff0c;Web Service是一个平台独立的、低耦合的、自包含的、基于可编程的web的应用程序&#xff0c;可使用开放的XML&#xff08;标准通用标记语言下的一个子集&#xff09;标准来描述、发…

DOS命令

当使用DOS命令时&#xff0c;可以在命令提示符下输入各种命令以执行不同的任务。以下是一些常见DOS命令的详细说明&#xff1a; dir (Directory): 列出当前目录中的文件和子目录。 用法: dir [drive:][path][filename] [/p] [/w] cd (Change Directory): 更改当前目录。 用法: …

Alist开源网盘搭建

官网&#xff1a;https://alist.nn.ci/zh/github下载地址&#xff1a;https://github.com/alist-org/alist/releases gitcode上也提供了源码:https://gitcode.com/mirrors/alist-org/alist/tags 源码安装使用自己研究,这里不讲解,较为复杂 我使⽤的版本:v3.29.1 我的下载地址:…

websocket项目 聊天室

1.项目概述 这个项目是一个基本的实时聊天应用&#xff0c;适用于小型团队或群体。提供了多个聊天室供用户选择。可以通过该代码进行进一步的扩展和定制&#xff0c;例如添加聊天机器人、改进界面等。 2.技术栈 flask&#xff0c;boostrapt&#xff0c;websocket&#xff0c…

adb调试软件下载 及 常用调试命令

一、软件下载 Windows版本&#xff1a;下载 Mac版本&#xff1a;下载 Linux版本&#xff1a;下载 二、常见调试命令 进入ADB调试 在文件路径栏输入cmd&#xff0c;回车&#xff0c;即可进入adb调试。注意&#xff1a;以下3条不要登录设备 shell &#xff08;一&#xff09;显…

大语言模型下载,huggingface和modelscope加速

huggingface 下载模型 如果服务器翻墙了&#xff0c;不用租机器 如果服务器没翻墙&#xff0c;可以建议使用下面的方式 可以租一台**autodl**不用显卡的机器&#xff0c;一小时只有1毛钱&#xff0c;启动学术加速&#xff0c;然后下载&#xff0c;下载完之后&#xff0c;用scp…

芯片烧写工具

问题描述 最近出了一个机器变砖的问题&#xff0c;一些用户使用的设备&#xff0c;头一天晚上用的好好的&#xff0c;第二天来一上电开机就起不来了。 然后就寄回来&#xff0c;返厂维修。一些是因为部分电子器件坏了&#xff0c;还有一些是文件系统问题&#xff0c;重新升级一…

GIT SourceTree 回滚提交

步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 在终端输入命令&#xff08;位置是项目目录下&#xff09; git push origin feature_mo2.1_r3_zhanx653 -f

深圳三维扫描分析/偏差检测模具型腔三维尺寸及形位偏差测量公司

CASAIM中科广电三维扫描模具型腔深圳案例&#xff1a; 模具型腔的三维扫描分析/偏差检测是一项重要的质量控制过程&#xff0c;旨在确保模具制造过程中的精确度和一致性。 CASAIM中科广电通过使用高精度的三维扫描设备&#xff0c;可以获取模具型腔的实际形状和尺寸数据&…

Python - 深夜数据结构与算法之 LRUCache

目录 一.引言 二.LRU Cache 简介 1.实现特性 2.工作流程 三.LRU Cache 实战 1.HashMap ListNode 2.OrderedDict 四.总结 一.引言 LRU 即 Least Recently Used 意为最近使用&#xff0c;它是一种局部 Cache 的缓存方法&#xff0c;用于存储最近使用的元素&#xff0c;…

Java 实现双链表

文章目录 双链表&#xff08;Doubly Linked List&#xff09;是一种常用的数据结构&#xff0c;它与单链表相似&#xff0c;但每个节点除了包含指向下一个节点的指针外&#xff0c;还包含一个指向前一个节点的指针。 双链表的节点由三部分组成&#xff1a;数据域&#xff08;存…

多线程应用场景

一 讨论多线程应用场景 现在很多高级语言都可以很方便的实现多线程&#xff0c;多线程实现很简单&#xff0c;易使用&#xff0c;反而因对多线程的应用场景不是很理解而乱用。 就从身边的事说起&#xff0c;甲同事提出他的一个接口因查询数据库近接近20多秒&#xff0c;于是马上…