博主主页: 码农派大星.
数据结构专栏:Java数据结构
数据库专栏:MySQL数据库
JavaEE专栏:JavaEE
软件测试专栏:软件测试
关注博主带你了解更多知识
目录
如果设置了@Param属性,#{...}需要使⽤参数.属性来获取
1. MyBatis概念
MyBatis是⼀款优秀的持久层框架,⽤于简化JDBC的开发
持久层:指的就是持久化操作的层,通常指数据访问层(dao),是⽤来操作数据库的
MyBatis是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库⼯具
2. MyBatis⼊⻔
Mybatis操作数据库的步骤:
1. 准备⼯作(创建springboot⼯程、数据库表准备、实体类)
2. 引⼊Mybatis的相关依赖,配置Mybatis(数据库连接信息)
3. 编写SQL语句(注解/XML)
4. 测试
2.1 Navicat 安装
这里我们会用到操作数据库的工具, 比如说Navigate ,小编为大家找好了,也感谢贡献者酷酷的洛克
Navigate 破解版 在这: 文件文件大小:95.9 M|https://kkdaj.lanzouq.com/iCJfT04o3pkh
教程: Navicat Premium 16 永久破解激活 - 酷酷的洛克 - 博客园文件
2.2 数据准备
安装完 Navicat 打开连接数据库就行
创建⽤⼾表
创建对应的实体类UserInfo
2.3 配置数据库连接
Mybatis中要连接数据库,需要数据库相关参数配置
MySQL驱动类登录名密码数据库连接字符串
application.yml⽂件,配置内容如下:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: '123456'
driver-class-name: com.mysql.cj.jdbc.Driver
2.4 完善持久层代码
在项⽬中,创建持久层接⼝UserInfoMapper
@Mapper
public interface UserInfoMapper {
@Select("select * from user_info")
List<UserInfo> queryUserInfos();
}
2.5 测试
1.自己书写测试代码
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/queryUserInfos")
public List<UserInfo> queryUserInfos(){
return userService.queryUserInfos();
}
}
@Service
public class UserService {
@Autowired
private UserInfoMapper userInfoMapper;
public List<UserInfo> queryUserInfos(){
return userInfoMapper.queryUserInfos();
}
}
测试结果: 成功查询出数据
2. 使⽤Idea⾃动⽣成测试
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void queryUserInfos() {
userInfoMapper.queryUserInfos().forEach(System.out::println);
}
}
运行成功:
3. MyBatis的基础操作
3.1 打印⽇志
打印日志需要先配置文件
application.yml, 配置内容如下:
mybatis:
configuration: # 配置打印 MyBatis 执行的 SQL
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
重启程序运行:
3.2 参数传递
如果mapper接⼝⽅法形参只有⼀个普通类型的参数,#{…}⾥⾯的属性名可以随便写,如:#{id}、# {value}。建议和参数名保持⼀致
可以通过 @Param ,设置参数的别名,如果使⽤ @Param 设置,#{...}⾥⾯的属性名必须和@Param 设置的⼀样
@Select("select * from user_info where id = #{id}")
UserInfo queryUserInfo(Integer id);
@Select("select * from user_info where id = #{id}")
UserInfo queryUserInfo(@Param("id") Integer id);
未加@Param
加@Param
测试:
@Test
void queryUserInfo() {
System.out.println(userInfoMapper.queryUserInfo(1));
}
结果:
查多个参数:
@Select("select * from user_info where id = #{id} and username = #{username}")
UserInfo queryUserInfoByIdAndName(Integer id, String username);
使用@Param重命名会报错
总结:
3.3 增(Insert)
@Insert("insert into user_info (username, password,age,gender,phone) " +
"values(#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo);
@Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("cxkun");
userInfo.setPassword("cxkun");
userInfo.setAge(33);
userInfo.setGender(2);
userInfo.setPhone("10086");
Integer result = userInfoMapper.insert(userInfo);
System.out.println("添加数据: "+ result);
}
测试结果:
如果设置了@Param属性,#{...}需要使⽤参数.属性来获取
@Insert("insert into user_info (username, password,age,gender,phone) " +
"values(#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})")
Integer insert2(@Param("userInfo") UserInfo userInfo);
测试结果:
自增Id
如果想要拿到⾃增id,需要在Mapper接⼝的⽅法上添加⼀个Options的注解
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into user_info (username, password,age,gender,phone) " +
"values(#{username},#{password},#{age},#{gender},#{phone})")
Integer insert(UserInfo userInfo);
3.4 删(Delete)
@Delete("delete from user_info where id = #{id}" )
Integer delete(Integer id);
3.5 改(Update)
@Update("update user_info set password =#{password} where id = #{id}")
Integer update(UserInfo userInfo);
3.6 查(Select)
1 起别名
@Select("select id,username,password,age,gender,phone," +
"delete_flag as deleteFlag,create_time as createTime,update_time as updateTime from user_info" )
List<UserInfo> queryUserInfos2();
2 结果映射
@Results({
@Result(column = "delete_flag",property = "deleteflag"),
@Result(column = "create_time",property = "createtime"),
@Result(column = "update_time",property = "updatetime")
})
@Select("select * from user_info" )
List<UserInfo> queryUserInfos3();
并且还可实现复用:
3 配置驼峰⾃动转换
4. MyBatis XML配置⽂件
Mybatis的开发有两种⽅式:
1. 注解 2. XML
使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能.如果需要实现复杂的SQL功能,建 议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中
步骤:
4.1 配置数据库连接字符串和MyBatis
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: '123456'
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
4.2 写持久层代码
持久层代码分两部分 1. ⽅法定义Interface 2. ⽅法实现:XXX.xml
1 添加mapper接⼝
import com.mybatis.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserInfoXmlMapper {
List<UserInfo> queryUserInfos();
}
2 添加UserInfoXMLMapper.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.mybatis.mapper.UserInfoXmlMapper">
<select id="queryUserInfos" resultType="com.mybatis.model.UserInfo">
select * from user_info;
</select>
</mapper>
检查好配置:
3 单元测试
@SpringBootTest
class UserInfoXmlMapperTest {
@Autowired
private UserInfoXmlMapper userInfoXmlMapper;
@Test
void queryUserInfos() {
userInfoXmlMapper.queryUserInfos().forEach(System.out::println);
}
}
测试成功:
4.3 查(Select)
1. 起别名 2. 结果映射 3. 开启驼峰命名
起别名和驼峰转换方法与注释一样,不在多说,接下来说结果映射
<resultMap id="XMLBaseMap" type="com.mybatis.model.UserInfo">
<id column="id" property="id"></id>
<result column="delete_flag" property="deleteFlag"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<select id="queryUserInfos2" resultMap="XMLBaseMap">
select * from user_info;
</select>
测试:
@Test
void queryUserInfos2() {
userInfoXmlMapper.queryUserInfos2().forEach(System.out::println);
}
测试成功:
4.4 增
UserInfoXmlMapper接⼝:
Integer insertUserInfo(UserInfo userInfo);
UserInfoMapper.xml实现:
<insert id="insertUserInfo">
insert into user_info (username, password, age,gender, phone)
values (#{username},#{password}, #{age},#{gender},#{phone})
</insert>
UserInfoXmlMapperTest测试:
@Test
void insertUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("cxk");
userInfo.setPassword("cxk");
userInfo.setGender(1);
userInfo.setAge(18);
userInfo.setPhone("13124124334");
userInfoXmlMapper.insertUserInfo(userInfo);
}
测试成功:
刷新数据库有新增的信息:
4.5 改
UserInfoXmlMapper接⼝:
Integer updateUserInfo(UserInfo userInfo);
UserInfoMapper.xml实现:
<update id="updateUserInfo">
update user_info set phone = #{phone} where id = #{id}
</update>
UserInfoXmlMapperTest测试:
@Test
void updateUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setPhone("12344444444");
userInfo.setId(13);
userInfoXmlMapper.updateUserInfo(userInfo);
}
测试成功:
4.6 删
UserInfoXmlMapper接⼝:
Integer deleteUserInfo(Integer id);
UserInfoMapper.xml实现:
<delete id="deleteUserInfo">
delete from user_info where id = #{id}
</delete>
UserInfoXmlMapperTest测试:
@Test
void deleteUserInfo() {
userInfoXmlMapper.deleteUserInfo(14);
}
测试成功:
5 多表查询
使用两张表进⾏多表关联查询
⽂章表的uid,对应⽤⼾表的id
补充实体类:
public class ArticleInfo {
private Integer id;
private String title;
private String content;
private Integer uid;
private String username;
private Integer age;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
根据uid查询作者的名称等相关信息
@Mapper
public interface ArticleInfoMapper {
@Select("select ta.*, tb.username, tb.age from articleinfo ta" +
" left join user_info tb on ta.uid=tb.id" +
" where ta.id = #{articleId}")
ArticleInfo queryArticleInfo(Integer articleId);
}
测试
@SpringBootTest
class ArticleInfoMapperTest {
@Autowired
private ArticleInfoMapper articleInfoMapper;
@Test
void queryArticleInfo() {
articleInfoMapper.queryArticleInfo(1);
}
}
查询成功:
6. #{} 和 ${}
@Select("select * from user_info where username = #{username}")
UserInfo queryUserInfoByName(String username);
@Select("select * from user_info where username = ${username}")
UserInfo queryUserInfoByName(String username);
6.1 #{} 和${}区别
#{} 和${} 的区别就是预编译SQL和即时SQL的区别
当客⼾发送⼀条SQL语句给服务器后,它的流程应该为:先解析语法和语义,校验SQL语句是否正确再优化SQL语句,制定执⾏计划最后 执⾏并返回结果
$是即时SQL(参数直接拼接),#是预编译SQL(参数通过占位的方式)
${} 允许直接将变量的值替换到 SQL 语句中(参数直接拼接的方式)。这种方式可能会导致 SQL 注入攻击,因为它直接将变量值拼接到 SQL 语句中,没有进行任何处理
#{}
:用于安全地插入参数(参数通过站位的方式),MyBatis 会为这些参数创建预处理语句,从而防止 SQL 注入攻击。
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译 (只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率
SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法
7. 排序功能
使⽤ ${} 可以实现排序查询,⽽使⽤ #{} 就不能实现排序查询了,SQL语句中,排序规则是不需要加引号,所以此时的${} 也不加引号
使⽤ #{} 查询时,desc前后⾃动给加了引号,导致sql错误
#{} 会根据参数类型判断是否拼接引号,如果参数类型为String就会加引号
改为${} 再试:
//排序
@Select("select * from user_info order by id ${order}")
List<UserInfo> queryUserInfoByOrder(String order);
测试成功:
除此之外,还有表名作为参数时,也只能使⽤ ${}
8. like查询
like 使⽤#{}报错
${}可以正确查出来,但是${}存在SQL注⼊的问题,所以不能直接使⽤${},使⽤mysql的内置函数concat()来处理
@Select("select * from user_info where username like CONCAT('%',#{name},'%')")
List<UserInfo> queryUserInfoByLike(String name);
测试成功:
9. 数据库连接池
数据库连接池技术,避免频繁的创建连接,销毁连接
数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接, ⽽不是再重新建⽴⼀个
没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀个新的连接对象,然后执⾏SQL语句,SQL 语句执⾏完,再关闭连接对象释放资源.这种重复的创建连接,销毁连接⽐较消耗资源
使⽤数据库连接池的情况:程序启动时,会在数据库连接池中创建⼀定数量的Connection对象,当客⼾ 请求数据库连接池,会从数据库连接池中获取Connection对象,然后执⾏SQL,SQL语句执⾏完,再把 Connection归还给连接池
优点: 1. 减少了⽹络开销 2. 资源重⽤ 3. 提升了系统的性能
使用
1. Hikari : SpringBoot默认使⽤的数据库连接池
2. Druid
把默认的数据库连接池切换为Druid数据库连接池,只需要引⼊相关依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
标签:username,初阶,--,数据库,userInfo,SQL,MyBatis,id,user
From: https://blog.csdn.net/jj666mhhh/article/details/143591277