mybatis
mybatis
1.什么是mybatis
mybatis是一款优秀的持久层框架,用于简化JDBC的开发
2.使用入门
【第一步】准备工作:创建数据库和表
【第二步】创建springboot工程,引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)
在springboot项目中,可以编写application.properties文件,配置数据库连接信息
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234
【第三步】实体类User、编写Mapper接口、SQL语句(注解/XML)
- 实体类的属性名与表中的字段名一一对应。
- @Mapper注解:表示是mybatis中的Mapper接口,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
- @Select注解:代表的就是select查询,用于书写select查询语句
@Mapper
public interface UserMapper {
//查询所有用户数据
@Select("select id, name, age, gender, phone from user")
public List<User> list();
}
【第四步】单元测试
在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。
该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。
@SpringBootTest
public class MybatisQuickstartApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testList(){
List<User> userList = userMapper.list();
for (User user : userList) {
System.out.println(user);
}
}
}
3.什么是JDBC?
JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。
原始的JDBC程序是如何操作数据库的
-
-
获取连接对象
-
执行SQL语句,返回执行结果
-
处理执行结果
-
释放资源
public class JdbcTest {
@Test
public void testJdbc() throws Exception {
//1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取数据库连接
String url="jdbc:mysql://127.0.0.1:3306/mybatis";
String username = "root";
String password = "1234";
Connection connection = DriverManager.getConnection(url, username, password);
//3. 执行SQL
Statement statement = connection.createStatement(); //操作SQL的对象
String sql="select id,name,age,gender,phone from user";
ResultSet rs = statement.executeQuery(sql);//SQL查询结果会封装在ResultSet对象中
List<User> userList = new ArrayList<>();//集合对象(用于存储User对象)
//4. 处理SQL执行结果
while (rs.next()){
//取出一行记录中id、name、age、gender、phone下的数据
int id = rs.getInt("id");
String name = rs.getString("name");
short age = rs.getShort("age");
short gender = rs.getShort("gender");
String phone = rs.getString("phone");
//把一行记录中的数据,封装到User对象中
User user = new User(id,name,age,gender,phone);
userList.add(user);//User对象添加到集合
}
//5. 释放资源
statement.close();
connection.close();
rs.close();
//遍历集合
for (User user : userList) {
System.out.println(user);
}
}
}
-----------------------------------------------------------------------------------------------------------------------
-
作用:
-
注册驱动
-
创建java代码和数据库之间的连接,即获取Connection对象
-
Connection(接口):建立数据库连接的对象
-
作用:用于建立java程序和数据库之间的连接
Statement(接口): 数据库操作对象(执行SQL语句的对象)。
-
作用:用于向数据库发送sql语句
ResultSet(接口):结果集对象(一张虚拟表)
-
作用:sql查询语句的执行结果会封装在ResultSet中
4.数据库连接池
4.1什么是数据库连接池
-
程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
-
客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
4.2连接池的好处
-
资源重用
-
提升系统响应速度
-
避免数据库连接遗漏
5.mybatis基础操作-删除
- SQL语句
-- 删除id=17的数据
delete from emp where id = 17;
- 接口方法
@Mapper
public interface EmpMapper {
//@Delete("delete from emp where id = 17")
//public void delete();
//以上delete操作的SQL语句中的id值写成固定的17,就表示只能删除id=17的用户数据
//SQL语句中的id值不能写成固定数值,需要变为动态的数值
//解决方案:在delete方法中添加一个参数(用户id),将方法中的参数,传给SQL语句
/**
* 根据id删除数据
* @param id 用户id
*/
@Delete("delete from emp where id = #{id}")//使用#{key}或${key}方式获取方法中的参数值
public void delete(Integer id);
}
@Delete注解:用于编写delete操作的SQL语句
- 测试
在单元测试类中通过@Autowired注解注入EmpMapper类型对象
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
@Autowired //从Spring的IOC容器中,获取类型是EmpMapper的对象并注入
private EmpMapper empMapper;
@Test
public void testDel(){
//调用删除方法
empMapper.delete(16);
}
}
如何打开日志输出
打开application.properties文件
#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
预编译的好处
更安全(防止SQL注入):将敏感字进行转义,保障SQL的安全性。
#{}和${}之间的区别?
#{}占位符在程序运行过程中会被翻译成?占位符,不会出现SQL注入漏洞问题,能预编译SQL。
${}占位符在程序行过程中不会被翻译成?占位符,是直接拼接值,可能出现SQL注入漏洞问题,不能预编译SQL
6.mybatis基础操作-新增
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert注解书写sql语句
useGeneratedKeys = true 表示需要获取生成的主键值。
keyProperty = "id" 将生成的主键值赋值给参数对象的id属性,也就是emp对象的id属性
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into emp( username, name, image,gender, job, entrydate,update_time ,create_time ,dept_id) values (#{username},#{name},#{image},#{gender},#{job},#{entrydate},#{createTime},#{updateTime},#{deptId})")
void insert(Emp emp);
7.mybatis基础操作更新
@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);
8.mybatis基础操作查询
SQL语句:select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp;
接口方法:
@Mapper
public interface EmpMapper {
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);
}
测试:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
@Autowired
private EmpMapper empMapper;
@Test
public void testGetById(){
Emp emp = empMapper.getById(1);
System.out.println(emp);
}
}
原因如下:
-
-
如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。
解决方案:
起别名 在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
@Select("select id, username, password, name, gender, image, job, entrydate, " +
"dept_id AS deptId, create_time AS createTime, update_time AS 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 id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);
开启驼峰命名
打开application.properties文件
# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true
模糊查询
使用MySQL提供的字符串拼接函数:concat('%' , '关键字' , '%')
@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> list(String name, Short gender, LocalDate begin, LocalDate end);
}
9.
-
-
XML映射文件的namespace属性为Mapper接口全限定名一致
-
XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
</mapper>
在Mybatis中提供了很多实现动态SQL的标签,我们学习Mybatis中的动态SQL就是掌握这些动态SQL标签。
9.2where标签和if标签
<if test="条件表达式">
要拼接的sql语句
</if>
<select id="list" resultType="com.itheima.pojo.Emp">
select * 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>
9.3set标签
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--更新操作-->
<update id="update">
update emp
<!-- 使用set标签,代替update语句中的set关键字 -->
<set>
<if test="username != null">
username=#{username},
</if>
<if test="name != null">
name=#{name},
</if>
<if test="gender != null">
gender=#{gender},
</if>
<if test="image != null">
image=#{image},
</if>
<if test="job != null">
job=#{job},
</if>
<if test="entrydate != null">
entrydate=#{entrydate},
</if>
<if test="deptId != null">
dept_id=#{deptId},
</if>
<if test="updateTime != null">
update_time=#{updateTime}
</if>
</set>
where id=#{id}
</update>
</mapper>
9.4foreach标签
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--删除操作-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
</mapper>
9.5sql和include标签
-
<sql>:定义可重用的SQL片段 -
<include>
<sql id="commonSelect">
select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>
<select id="list" resultType="com.itheima.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>
浙公网安备 33010602011771号