1、 MyBatis
1.1 MyBaris入门
这是一个特别好用的数据库的工具,直接使用了数据库连接池,它基于注解和配置文件使用,通常搭配IOC容器一起使用。
配置文件格式
#驱动类名称
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=040118
@Mapper//在运行时,会自动生成该接口的实现类对象,并且将该对象交给IOC容器管理
public interface UserMapper {
//查询全部用户信息
@Select("select * from user")
public List<User> list();
}
还需使用java实体类来封装查询到的结果
1.2 数据库连接池
-
官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)
- 功能:获取连接
public Connection getConnection() throws SQLException;
- 第三方组织必须按照DataSource接口实现
常见连接池品牌
- C3P0
- DBCP
- Druid(德鲁伊)
- Hikari(追光者)
Springboot中自带的是追光者Hikari
Druid是阿里巴巴的开源项目
如何切换度路易连接池
-
参考官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
- 在pom.xml文件中引入依赖
<dependency> <!-- Druid连接池依赖 --> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency>
- 在application.properties中引入数据库连接配置
方式1:
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis spring.datasource.druid.username=root spring.datasource.druid.password=1234
方式2:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis spring.datasource.username=root spring.datasource.password=1234
2. Lombok
说人话:写一个实体类的时候,太多的get Set 构造啥的,太臃肿了,使用了Lombok的注解之后啊,只需要写属性就好了。
Lombok是一个实用的Java类库,可以通过简单的注解来简化和消除一些必须有但显得很臃肿的Java代码。
注解 | 作用 |
---|---|
@Getter/@Setter | 为所有的属性提供get/set方法 |
@ToString | 会给类自动生成易阅读的 toString 方法 |
@EqualsAndHashCode | 根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法 |
@Data | 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode |
@NoArgsConstructor | 为实体类生成无参的构造器方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 |
当然啦,要先引入Lombok的依赖:
<!-- 在springboot的父工程中,已经集成了lombok并指定了版本号,故当前引入依赖时不需要指定version -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
然后就能在实体类上添加注解了!
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private Short age;
private Short gender;
private String phone;
}
这真的是太方便了捏!
import lombok.*;
//使用Lombok的注解
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private Short age;
private Short gender;
private String phone;
}
3 、 MyBatis基础操作
不就是增删改查吗?EZ
使用预编译,性能更高,还能防止SQL注入
3.1 删
//根据ID删除数据
@Delete("delete from emp where id = #{id}")
public int delete(Integer id);
使用#{}或${}占位符
- #{…}
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
- 使用时机:参数传递,都使用#{…}
- ${…}
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
- 使用时机:如果对表名、列表进行动态设置时使用
3.2 增
@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);
3.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);
@Test
public void testUpdate(){
Emp emp = new Emp();
emp.setId(18);
emp.setUsername("Tom1");
emp.setName("汤姆1");
emp.setImage("1.jpg");
emp.setGender((short)1);
emp.setJob((short)1);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setUpdateTime(LocalDateTime.now());
emp.setDeptId(1);
//调用方法,修改员工数据
empMapper.update(emp);
}
3.4 查
我们看到查询返回的结果中大部分字段是有值的,但是deptId,createTime,updateTime这几个字段是没有值的,而数据库中是有对应的字段值的,这是为什么呢?
- 起别名
@Select("select id,id, username, password, name, gender, image, job, entrydate, dept_id deptId, create_time createTime, update_time updateTime from emp where id = #{id}")
- 结果映射
@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}")
- 开启驼峰命名
//大招 下划线转驼峰
@Select("select * from emp where id = #{id}")
#开启MyBatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
3.5 条件查询
使用MySQL提供的字符串拼接函数:concat(‘%’ , ‘关键字’ , ‘%’)
//条件查询员工
@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);
4、 XML映射文件
接下来学习通过XML文件来执行SQL文件
4.1 规范
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下==(同包同名)==
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
<!--resultType 单条记录所封装的类型-->
<mapper namespace="com.czc.mapper.EmpMapper">
<select id="list" resultType="com.czc.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>
如何选择使用注解还是XML文件来定义SQL语句呢,自己掂量。
5、 动态SQL
随着用户的输入或外部条件的变化而变化的SQL语句,我们称之为动态SQL。
5.1 SQL-----if
使用if标签来改造SQL语句,满足条件就拼接,不满足就不拼接,这真的是太吊啦!
- 原有的SQL语句
<select id="list" resultType="com.itheima.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>
-
动态SQL语句
在里面设置test属性
<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>
order by update_time desc
</select>
这时,当第一个if没有东西,但是第二个if有,就会报错,这是我在老师说之前发现的,解决方法是:删掉"where"使用标签将这些包裹起来,这样,如果满足条件,他就会拼接到SQL中,并且会根据实际情况删掉"and"这个单词,如果不满足,就不会拼接。
以上问题的解决方案:使用<where>
标签代替SQL语句中的where关键字
<where>
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
<where>
<!-- if做为where标签的子元素 -->
<if test="name != null">
and 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>
where id=#{id}
</update>
同理,使用替换set 可以去除多余的逗号
<!-- 动态更新员工信息-->
<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>
小结
-
<if>
-
用于判断条件是否成立,如果条件为true,则拼接SQL
-
形式:
<if test="name != null"> … </if>
-
-
<where>
- where元素只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR
-
<set>
- 动态地在行首插入 SET 关键字,并会删掉额外的逗号。(用在update语句中)
5.2 SQL—ForEach
一眼循环
<!-- 批量删除员工 (18,19,20)-->
<!--
collection:遍历集合
item: 遍历出来的元素
separator:分隔符
open:开始前拼接的SQL片段
close:结束时拼接的SQL片段
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
小结:
foreach的属性:
collection:遍历集合
item: 遍历出来的元素
separator:分隔符
open:开始前拼接的SQL片段
close:结束时拼接的SQL片段
5.3 SQL— sql include
这两个配套使用哦!
在mapper里面抽取SQL语句
<sql id="commonSelect">
select id,id, username, password, name, gender, image, job, entrydate, dept_id , create_time , update_time
from emp
</sql>
然后,在原来的位置上引用
<include refid="commonSelect"></include>