Mybatis
从实体类、Mapper、注解 SQL 和配置文件开始,记录 Mybatis 查询与项目集成的入门过程。
入门
入门程序
目的:使用Mybatis查询表中所有分类信息。
- 第一步:构建一个mybaits项目,一个Category实体类(用以储存查询到的信息),数据库表category 在构建Category实体类时,需要有一个全参构造器和所有get()set()函数,字段列表类型,名称需要与数据库的字段列表一致。其中tinyint使用Short代替,varchar使用String代替。
public class Category {
private Integer id;
private String name;
private Short type;
private Short sort;
private Short status;
public Category(Integer id, String name, Short type, Short sort, Short status) {
this.id = id;
this.name = name;
this.type = type;
this.sort = sort;
this.status = status;
}
get()与set()函数
toString()函数
}
- 引入mybatis相关依赖,并配置mybatis 打开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
- 使用注解(或xml)编写sql语句 声明一个CategoryMapper接口,在其前面加上@Mapper注解。这个注解会自动将其封装成实体类(可以使用其类对象)。
@Mapper
public interface CategoryMapper {
//Select注解表示需要执行的sql语句
@Select("select * from category")
public List<Category> list(); //使用List来接受多行数据
}
在test文件中进行测试。使用@Autowired来自动将相关依赖注入接口类对象。
@Autowired
private CategoryMapper categoryMapper;
@Test
void contextLoads() {
List<Category> categoryList = categoryMapper.list();
categoryList.stream().forEach(category -> {
System.out.println(category);
});
}
配置SQL提示
@Select注解中的字符串并没有自动联想与自动纠错。选择@Select中的字符串,找到Show Context Actions->Inject language reference->MySql即可
JDBC
JDBC是sun公司提供的一套操作所有关系型数据库的规范,即接口。各个数据库厂商自己实现接口,提供数据库驱动jar包。使用JDBC编程时,执行的代码是jar包中的实现类。
Lombok
Lombok是一个实用的java类库,能通过注解的形式自动生成构造器等函数。
| **注解** | **作用** |
| @Getter/@Setter | 添加get/set方法 |
| @ToString | 生成易阅读的tostring方法 |
| @EqualsAndHashCode | 重写equals方法和hashCode方法 |
| @Data | 提供了更综合的生成代码功能(涵盖以上) |
| @NoArgsConstructor | 无参构造 |
| @AllArgsConstructor | 全参构造 |
//根据ID删除数据 @Delete(“delete from mybatis.drinks where id = #{id}”) //#{}是一个占位符 public int delete(Integer deleteId); //返回值代表操作的记录数 }
### **预编译SQL**
默认情况下,mybatis日志不会输出,使用
```plain text
# 打开mybatis的日志,并输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
来将日志输出到控制台。
- 预编译SQL 当使用#{}来指定参数时,会出现预编译SQL,#{}被解释为?,例如:
==> Preparing: delete from mybatis.drinks where id = ?
==> Parameters: 22(Integer)
使用预编译SQL性能更高,且更加安全(防止SQL注入)。
- SQL注入 SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,达到执行代码对服务器进行攻击的操作。 例如,登录的SQL写法:
select count(*) from emp where username = 'username' and password = '1234'
而当输入的密码为’or’1’ = ’1时,SQL语句将变为:
select from(*) from emp where username = 'username' and password = ''or'1' = '1'
判断语句永远为真。这样就达到了攻击服务器的目的。 而使用预编译SQL即可预防这种情况。当然也可以使用${}使用拼接SQL语句,使用场景很少。
新增
使用@Insert注解,具体实现如下:
@Insert("insert into mybatis.drinks(id, name, category_id, price, img, description, status, update_time)" +
" values (#{id}, #{name}, #{categoryId}, #{price}, #{img}, #{description}, #{status}, #{updateTime}) ")
public void insert(Drinks drinks);
可以将传递的参数封装在一个对象中,且作为参数传递。注意:#{}中的参数需要与对象中一致,即遵守驼峰命名法。
主键返回
将封装的实体类传递给insert函数后,实体类会被清空,因此无法拿到当初填入的主键。可以使用@Options来进行一些设置,其中,keyProperty表示返回的主键 useGeneratedKeys = true表示将返回的主键值封装在字段中。
@Options(keyProperty = "id", useGeneratedKeys = true)
//使用@Options注解配置主键信息,useGeneratedKeys = true表示将返回的主键值封装在字段中
@Insert("insert into mybatis.drinks(id, name, category_id, price, img, description, status, update_time)" +
" values (#{id}, #{name}, #{categoryId}, #{price}, #{img}, #{description}, #{status}, #{updateTime}) ")
public void insert2(Drinks drinks);
更新
@Update("update mybatis.user set id = #{id}, username = #{username}, password = #{password}")
public void update(Users users);
查询
@Select("select * from mybatis.drinks where id = #{id}")
public Drinks getById(Integer id);
查询方法返回值可以是一个集合(用来储存多个返回内容),可以是一个对象(返回单个元素),int(使用了count()函数)。 如果实体属性名与数据库表查询返回的字段名一致,mybatis会自动封装;如果不一致,则不会自动封装。解决方法如下:
- 方案一:起别名
@Select("select id, name, category_id categoryId, price, img, description, status, update_time updateTime from mybatis.drinks where id = #{id}")
public Drinks getById(Integer id);
- 方案二:使用@Results和@Result注解自动映射
@Results({
@Result(column = "category_id", property = "categoryId"),
@Result(column = "update_time", property = "updateTime"),
})
@Select("select * from mybatis.drinks where id = #{id}")
public Drinks getById(Integer id);
- 方案三:使用mybatis驼峰命名自动映射
在application.properties中配置
mybatis.configuration.map-underscore-to-camel-case=true即可。使用这种方法需要严格遵守:数据库中字段使用下划线命名,mybatis中使用驼峰命名法。
条件查询
目的:对name进行模糊查询,查询指定价格范围内的内容并以倒序排序:
@Select("select * from mybatis.drinks where name like concat('%', #{name}, '%') and status = #{status} and price between #{price1} and #{price2} order by category_id desc")
public List<Drinks> getBy(String name, Integer status, Double price1, Double price2);
需要注意的是,name后不是等于,是like;而且不能使用预编译SQL,需要使用字符串拼接函数concat()