入门
Mybatis是一款持久层框架,简化了JDBC的操作。
- 持久层(DAO):完成持久化工作的代码块;
- 持久化:将程序的数据在持久状态和瞬时状态转化的过程
Mybatis+SpringBoot=只关注application.properties+mapper接口
配置:application.properties
#配置数据库连接信息 -四要素
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/db01
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=*****
@Mapper:
@Mapper
注解用于标记一个接口是 MyBatis 的 Mapper 接口。当在接口上添加了@Mapper
注解后,MyBatis 会为这个接口创建一个动态代理对象。这个代理对象能够在运行时,将接口方法的调用转换为对 SQL 语句的执行。
例:UserMapper.java 接口
@Mapper
public interface UserMapper {
//查询全部用户信息
@Select("Select * from user")
public List<User> list();
}
@Autowired
注解注入UserMapper
来调用其方法。例:
@Autowired
private UserMapper userMapper;
public void testListUser(){
userMapper.list().forEach(user -> {
System.out.println(user.toString());
});
}
数据库连接池:
是个容器,负责分配、管理数据库连接:Connection
目的:资源重用、提升速度、避免连接遗漏
SpringBoot默认使用HiKari 连接池
参数占位符 #{…}与 ${…}
#{…}:
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值。也可以防止SQL注入。
- 使用动机:参数传递,都使用#{…}
${…}:
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题。
- 使用动机:对表名、列表进行动态设置。
输出SQL到控制台:
在application.properties中:
#输出SQL到控制台
mybatis.configuration.log-impl= org.apache.ibatis.logging.stdout.StdOutImpl
基础操作
1 删除:(根据id)
@Mapper
public interface EmpMapper {
@Delete("DELETE from emp where id=#{id}")
public void delete(Integer id);
}
2 新增:
注意此处将带下划线的变量转化为小驼峰形式:
MyBatis 在处理#{deptId}
这样的占位符时,会尝试根据一定的规则将其与数据库表列进行匹配。如果数据库表中有dept_id
列,它可以根据内置的命名转换规则将 Java 对象属性deptId
正确地映射到dept_id
列,方便数据的存取操作。
其他地方的下划线到驼峰的映射,需要在配置中打开驼峰命名映射开关:
mybatis.configuration.map-underscore-to-camel-case=true
useGeneratedKeys = true
表示希望获取数据库自动生成的主键值,keyProperty
则指定了将这个主键值设置到哪个 Java 对象的属性中。
EmpMapper:
@Options(keyProperty = "id",useGeneratedKeys = true)//获取返回的主键
@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);
test:
public void testInsert(){
Emp emp=new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short)1);
emp.setImage("1.jpg");
emp.setJob((short)1);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setDeptId(1);
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
}
3 修改:
@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);
4 查询:
根据id查询:
@Select("Select * from emp where id=#{id}")
public Emp getByID(Integer id);
根据条件查询:
注意此处@Param(“begin”)加不加要看SB版本,2.x一般不用
@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(@Param("name") String name,@Param("gender") short gender,@Param("begin") LocalDate begin,@Param("end") LocalDate end);
@Test
public void testList(){
List<Emp> list = empMapper.list("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2030, 1, 1));
System.out.println(list);
}
xml 映射文件
“使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
”选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。”–入门_MyBatis中文网
XML映射文件定义规范
- XML文件的名称与Mapper接口名称一致,并且放置在相同包下(同包同名)。
- XML文件的namespace属性为Mapper接口全限定名一致。
- XML文件中sql语句的id与Mapper接口中的方法名一致。
动态SQL
随着用户输入或外部条件而变化的SQL语句–动态SQL
- <if> 用于判断条件是否成立,使用test属性进行条件判断,如果条件为true,则拼接SQL
- <where> where只会在子元素有内容的情况下才插入where子句。而且会自动去除子句开头不合适的 AND 和 OR 。
- <set> 动态的在行首插入 SET 关键字,并会删掉不合适的逗号(用在update中)
- <foreach>
- collection:集合名(与使用方法中的集合名一致 )
- item: 单个元素
- separator : 分隔符
- open: 遍历开始前拼接的片段
- close : 遍历结束后拼接的片段
- <sql> 和 <include>
- <sql> 定义可重用的SQL片段
- <include> :通过属性refid,指定包含的sql片段。
例1:
<?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.itheima.mapper.EmpMapper">
<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>
<update id="update2">
UPDATE emp
<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>
- <foreach>
- collection:集合名(与使用方法中的集合名一致 )
- item: 单个元素
- separator : 分隔符
- open: 遍历开始前拼接的片段
- close : 遍历结束后拼接的片段