Mybatis初步认识
spring boot的web项目为了降低模块之间的耦合度,基本上都采用三层结构,其中dao层负责与文件或DB交互获取数据,从而为上层的service方法提供接口。Java项目中与DBMS交互,需要通过标准的JDBC接口,使用原始的jdbc会使代码非常繁琐,需要编写很多流程化的代码。mybatis是一个持久层框架,免除了几乎所有jdbc代码、设置参数和获取结果集的工作。
使用mybatis的基本步骤总结为三步:
- 准备数据库表和对应的实体类定义。
- 引入mybatis和其他的依赖,进行datasource配置。
- 准备mapper接口,通过注解或xml的形式编写SQL语句。这是重点。
通过注解编写SQL语句,需要定义mapper接口类,在接口上加上@Mapper
注解,并在接口内定义的方法上加上SQL语句的注解@Select
等等。service层中可以直接调用对应的方法,开发者不需要定义实现类,这个工作是由框架负责实现的,mybatis还会将实现类对象交给IoC容器管理。
public interface UserMapper {@Select("select * from user")public List<User> list();
}
数据库连接池
新建和销毁数据库连接开销较大,所以使用连接池的方法在初始化阶段创建一定数量的连接并进行统一管理,在需要时分配,不需要时回收,可以提高运行效率、资源利用率。官方定义了数据库连接池的接口DataSource
,由第三方库的开发者来实现。
mybatis的默认实现使用的是叫做Hikari的连接池,另一种常用的连接池实现是阿里开源的Druid。可以通过配置来更换使用不同的实现。
Lombok
定义Java实体类时除了声明私有属性之外,还需要为每个属性提供getter和setter、以及构造函数,非常麻烦。lombok针对此情况提供了可以自动生成这些函数的注解。要使用这个库需要引入对应的依赖。
注解 | 作用 |
---|---|
@Getter 和@Setter |
为所有属性提供getter和setter |
@ToString |
生成toString 方法 |
@EqualsAndHashCode |
更加非静态字段重写equals 和hashCode 方法 |
@Data |
综合上面四个注解 |
@NoArgsConstructor 和@AllArgsConstructor |
无参构造和除静态字段之外的全参数构造函数 |
mybatis细节
首先,实体类中的属性定义按照Java的通常规范使用驼峰命名法,而数据库字段通常使用下划线命名。
很多情况下,SQL语句都是动态的,需要根据参数进行查询和修改,每条SQL语句与mapper的一个方法对应,因此在调用该方法时可以传入一个参数,在SQL语句中使用参数占位符#{...}
。注意使用占位符的SQL语句会产生预编译的语句。这个占位符用于参数的动态传入,一般都使用它,还有一种占位符是${...}
,这个占位符是直接拼接,可以用于列名、表名的动态指定以及字符串匹配的引号中,所以使用场景较少。
@Mapper
public interface EmpMapper {
@Delete("delete from emp where id = #{id}")
public void delete(Integer id);
}
注意,SQL语句(比如上面的delete)是有返回值的,返回值为该语句影响的记录数量,在不需要该返回值时,将方法的返回值设置为了void
。
mybatis具体执行的sql语句默认是无法看到的,需要在项目配置文件中打开mybatis的日志输出,并指定输出方向(终端输出或日志文件等)。
在插入记录时,考虑到实际使用场景,由于需要传入很多个参数,所以参数列表很长,不易读且不好维护,实践中建议封装到类对象中再传参。注意这里占位符中的名字应该要与对象中的属性名保持一致。
实际插入场景中还可能有需要在新增记录后获取新记录的主键值,可以在接口方法上添加下面这个注解:
@Options(keyProperty = "id", useGeneratedKeys = true)
它表示将新生成的主键,绑定到名为id
的属性中。
上面记录了关于删除、插入的方法,更新的方法是类似的。
下面记录查询的相关内容。查询方法的一个不同点在于查询的结果通过接口方法的返回值提供给调用者(通常是service层的方法)。另一个问题在于前面提到的对应字段的名字不同(驼峰命名与下划线命名)。要解决这个问题,可以有几个方法:
- 在SQL语句中给有问题的字段起别名。
- 在接口方法上通过
@Results
和@Result
注解手动映射名字。 - 打开mybatis的驼峰命名自动映射。显然,我们需要注意名字的拼写不要对应不上。
使用xml文件编写SQL语句和映射关系
前面提到mybatis中编写SQL语句可以使用注解或者单独的xml配置文件。后者有三点主要规范需要遵守(保证框架能够找到正确的语句来执行):
- xml文件的名称需要与mapper接口的名称一致,而且xml文件需要放在mapper接口源文件相同包内,即同包同名。而且通常都是一个接口对应一个xml文件。
- xml文件的namespace属性需要与mapper接口的全限定名字一致。
- xml文件中sql语句的
id
需要与mapper接口中定义的方法名字一致,同时返回值类型returnType
也要一致。
由于这种xml文件的格式和约束(开头的几行)是固定的,而且很难记,所以基本需要从网上的模板上直接拷贝。同样的,具体的写法网上的例子也很多,不应该死记硬背。
mybatis的动态sql功能
一个典型的动态sql使用场景是程序为用户提供多个筛选查询条件时,用户可能只会使用其中的几个筛选条件,此时其他的条件是空的,如果硬编码所有条件到SQL语句中,显然会出现语法错误,此时就可以使用动态SQL功能。动态SQL就是随输入或外部条件变化的SQL语句。
mybatis提供了很多动态sql功能,如if
、foreach
、引入sql片段等等,具体如何使用可以直接从网上搜索。需要注意的是这种比较复杂的sql显然应该在xml配置中编写,强行要使用注解的形式只会导致代码臃肿。
总的来说,这些东西常用而且网上资料非常多,这里记录主要用于整理并整合理解。