MyBatisPlus学习笔记 学习使用看这一篇就够了

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MyBatisPlus学习笔记 学习使用看这一篇就够了

工具接口及类


BaseMapper

BaseMapper是mp提供给我们用于增强mapper接口方法:覆盖了大量的针对于单表的查询操作


public interface BaseMapper<T> extends Mapper<T> {
    //新增
    int insert(T entity);
    int deleteById(Serializable id);
    //根据字段删除
    int deleteByMap(@Param("cm") Map<String, Object> columnMap);
    int delete(@Param("ew") Wrapper<T> wrapper);
    //批量删除
    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    //单条更新
    int updateById(@Param("et") T entity);
    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
    //单条查询根据id
    T selectById(Serializable id);
    //查询多条记录根据id
    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    //查询多条记录根据属性字段
    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
    T selectOne(@Param("ew") Wrapper<T> queryWrapper);
    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}



IService与ServiceImpl(接口定义与实现)

Service CRUD 接口—官方文档


下面是ServiceImpl给我们实现的抽象类方法



你能想到的单表查询几乎都有。


public interface IService<T> {
    int DEFAULT_BATCH_SIZE = 1000;
    default boolean save(T entity) {
        return SqlHelper.retBool(this.getBaseMapper().insert(entity));
    }
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveBatch(Collection<T> entityList) {
        return this.saveBatch(entityList, 1000);
    }
    boolean saveBatch(Collection<T> entityList, int batchSize);
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        return this.saveOrUpdateBatch(entityList, 1000);
    }
    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
    default boolean removeById(Serializable id) {
        return SqlHelper.retBool(this.getBaseMapper().deleteById(id));
    }
    default boolean removeByMap(Map<String, Object> columnMap) {
        Assert.notEmpty(columnMap, "error: columnMap must not be empty", new Object[0]);
        return SqlHelper.retBool(this.getBaseMapper().deleteByMap(columnMap));
    }
    default boolean remove(Wrapper<T> queryWrapper) {
        return SqlHelper.retBool(this.getBaseMapper().delete(queryWrapper));
    }
    default boolean removeByIds(Collection<? extends Serializable> idList) {
        return CollectionUtils.isEmpty(idList) ? false : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(idList));
    }
    default boolean updateById(T entity) {
        return SqlHelper.retBool(this.getBaseMapper().updateById(entity));
    }
    default boolean update(Wrapper<T> updateWrapper) {
        return this.update((Object)null, updateWrapper);
    }
    default boolean update(T entity, Wrapper<T> updateWrapper) {
        return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
    }
    @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean updateBatchById(Collection<T> entityList) {
        return this.updateBatchById(entityList, 1000);
    }
    boolean updateBatchById(Collection<T> entityList, int batchSize);
    boolean saveOrUpdate(T entity);
    default T getById(Serializable id) {
        return this.getBaseMapper().selectById(id);
    }
    default List<T> listByIds(Collection<? extends Serializable> idList) {
        return this.getBaseMapper().selectBatchIds(idList);
    }
    default List<T> listByMap(Map<String, Object> columnMap) {
        return this.getBaseMapper().selectByMap(columnMap);
    }
    default T getOne(Wrapper<T> queryWrapper) {
        return this.getOne(queryWrapper, true);
    }
    T getOne(Wrapper<T> queryWrapper, boolean throwEx);
    Map<String, Object> getMap(Wrapper<T> queryWrapper);
    <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
    default int count() {
        return this.count(Wrappers.emptyWrapper());
    }
    default int count(Wrapper<T> queryWrapper) {
        return SqlHelper.retCount(this.getBaseMapper().selectCount(queryWrapper));
    }
    default List<T> list(Wrapper<T> queryWrapper) {
        return this.getBaseMapper().selectList(queryWrapper);
    }
    default List<T> list() {
        return this.list(Wrappers.emptyWrapper());
    }
    default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        return this.getBaseMapper().selectPage(page, queryWrapper);
    }
    default <E extends IPage<T>> E page(E page) {
        return this.page(page, Wrappers.emptyWrapper());
    }
    default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
        return this.getBaseMapper().selectMaps(queryWrapper);
    }
    default List<Map<String, Object>> listMaps() {
        return this.listMaps(Wrappers.emptyWrapper());
    }
    default List<Object> listObjs() {
        return this.listObjs(Function.identity());
    }
    default <V> List<V> listObjs(Function<? super Object, V> mapper) {
        return this.listObjs(Wrappers.emptyWrapper(), mapper);
    }
    default List<Object> listObjs(Wrapper<T> queryWrapper) {
        return this.listObjs(queryWrapper, Function.identity());
    }
    default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
        return (List)this.getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
    }
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {
        return this.getBaseMapper().selectMapsPage(page, queryWrapper);
    }
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {
        return this.pageMaps(page, Wrappers.emptyWrapper());
    }
    BaseMapper<T> getBaseMapper();
    default QueryChainWrapper<T> query() {
        return ChainWrappers.queryChain(this.getBaseMapper());
    }
    default LambdaQueryChainWrapper<T> lambdaQuery() {
        return ChainWrappers.lambdaQueryChain(this.getBaseMapper());
    }
    default UpdateChainWrapper<T> update() {
        return ChainWrappers.updateChain(this.getBaseMapper());
    }
    default LambdaUpdateChainWrapper<T> lambdaUpdate() {
        return ChainWrappers.lambdaUpdateChain(this.getBaseMapper());
    }
    default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
        return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
    }
}



IPage与Page



在Page对象中,包含了关于分页的相关信息,其中包含对应的查询结果集records以及对于分页的相关属性:



可以说满足了基本的需求了。



一、springboot集成Mybatis plus实现CRUD


Mapper CRUD 接口


前提准备



引入依赖:


<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>


yml配置项:


spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/mybatisplusExer?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    # 启动时需要初始化的建表sql语句
    schema: classpath:sql/schema.sql
    # 执行好就修改为never
    initialization-mode: always  # always为始终执行初始化,embedded只初始化内存数据库(默认值),如h2等,never为不执行初始化
#控制台打印sql(默认不会有打印sql语句)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 默认开启时会进行pojo字段映射如:lastName => last_name
    mapUnderscoreToCamelCase: false   # 取消自动驼峰命名规则映射(默认是开启的),这里仅仅是用于测试



sql:


DROP TABLE IF EXISTS user;
CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');


pojo:


/**
 * @ClassName User
 * @Author ChangLu
 * @Date 2021/8/16 22:11
 * @Description TODO
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User {  //mp会默认将pojo类名当做表名(首字母小写),若是类名与表名不一致可使用注解
    //默认会识别id作为主键,这里是对id自动生成进行设置: IdType.AUTO为自动,还有其他很多策略
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    // 设置表字段别名(当表属性不一致时即可进行指定)  默认是自动开启别名转换的(这里只是为了熟悉使用)
    @TableField("last_name")
    private String lastName;  //建议pojo字段名与表名像lastName=>last_name要对应,否则使用(如name=>last_name)包装器select()查询返回赋值会无效。
    private Integer age;
    private String email;
}



默认mybatis-plus中会将你的pojo类自动进行转换,如字段lastName,之后来查询数据库会自动转为last_name来进行查询。

若是你插入一条数据的id(mp默认会认为你的id为主键id)没有设置,mp会自动帮你生成一个全局唯一的id(字符串)!并且你插入后该对象就会得到对应自动生成的id值。

UserMapper:


/**
 * @ClassName UserMapper
 * @Author ChangLu
 * @Date 2021/8/16 22:11
 * @Description TODO
 */
public interface UserMapper extends BaseMapper<User> {
}


springboot启动类上标注自动扫描mapper包:


@MapperScan("com.changlu.mybatisplusexer.mapper")



CRUD操作


这里暂时没有Wrapper相关的操作,只是进行了对selectByMap及deleteByMap以及其他普通的测试用例,其是根据传入map的属性来进行字段查询的,可设置多个字段,这里仅有一个字段。


特别说明的是:mp中对于查询的键值对,传入与数据库中不同类型的也可以兼容,真的是强大呀,例如数据库中的age字段为int类型,你设置map属性字段中传入put(“age”,“20”)也完全是ok的。


import com.changlu.mybatisplusexer.mapper.UserMapper;
import com.changlu.mybatisplusexer.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
class MybatisplusexerApplicationTests {
    @Resource
    private UserMapper userMapper;
    @Test
    void queryAll() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }
    @Test
    void query(){
        System.out.println(userMapper.selectById(1));
    }
    @Test
    void query2(){  //selectByMap测试:根据条件筛选
        Map<String, Object> columnMap = new HashMap<>(1);
        columnMap.put("age",20);//条件为age=20
        List<User> users = userMapper.selectByMap(columnMap);
        System.out.println(users);
    }
    @Test
    void insert(){
        User user = new User(null, "changlu", 18, "939974883@qq.com");
        //执行保存sql前会先生成id到user中
        int result = userMapper.insert(user);
        System.out.println("user=>"+user+",result=>"+result);
    }
    @Test
    public void delete(){
        int result = userMapper.deleteById(1);
        System.out.println(result);
    }
    @Test
    public void delete2(){ //deleteByMap:根据指定字段删除
        Map<String, Object> columnMap = new HashMap<>(1);
        columnMap.put("age","20");//条件为age=20,
        int result = userMapper.deleteByMap(columnMap);
        System.out.println(result);
    }
    @Test
    public void update(){
        User user = new User((long)2, "changlu", 20, "939974883@qq.com");
        int result = userMapper.updateById(user);
        System.out.println(result);
    }
}


二、通用IService使用


在一中介绍的是对mapper接口进行的增强,在mp中还可以对service进行增强,也就是说一些常见的普通的service方法已经帮你进行封账好了,能够更快的进行一系列的操作。


Service CRUD 接口


说明:


//更新操作
//①若是更新某个model实体类,使用updateWrapper一定要进行指定id,否则就会更新整张表
//②若是批量对多个model的某个字段进行更新,调用方法
updateBatchById()
save():执行完后返回的是一个布尔值,表示是否插入成功,并且若是你没有填写id,会自动先生成主键到指定实体类中,再进行执行sql保存操作


准备


在示例一的基础上,我们来添加service接口以及service实现类,对应的接口需要实现IService,实现类需要继承一个抽象Service,同样也是mp给我们封装号的对应增强方法接口的实现体。



UserService:service接口定义
public interface UserService extends IService<User> {
}


UserServiceImpl:实现类定义


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}



测试


在mp给我们提供的service方法中,对于增删改操作也都包含了对应的事务处理,总体来说还是特别方便的!


@SpringBootTest
class MybatisplusexerApplicationTests {
    @Autowired
    private UserService userService;
    //saveOrUpdate:先根据id查,若是有则进行更新,没有进行插入
    @Test
    public void saveOrUpdate(){
        //测试插入
        User user = new User((long)1,"changlu",18,"9999");
        boolean b = userService.saveOrUpdate(user);//true:成功;false:失败
        System.out.println(b);
    }
    //saveOrUpdate:先根据id查,若是有则进行更新,没有进行插入
    @Test
    public void saveOrUpdate2(){
        //测试更新
        User user = new User((long)1,"liner",22,"368");
        boolean b = userService.saveOrUpdate(user);
        System.out.println(b);
    }
    //listByIds:根据多个id来进行批量查询。(底层采用in方式来进行查询)
    @Test
    public void query(){
        List<User> users = userService.listByIds(Arrays.asList(1, 3, 5));
        System.out.println(users);
    }
}




三、分页查询


3.1中的分页方法只对调用IService里的分页方法才有效!


我们编写请求实现类时,若是进行分页可以直接继承下面的实体类就是表示分页和:


@Data
public class BasePage implements Serializable {
    private static final long serialVersionUID = 8491572200460447988L;
    protected long size = 10;
    protected long current = 1;
}



3.1、借助mp的分页插件


准备 分页插件


在mp的Iservice中提高了四个分页方法:



在BaseMapper中提供了两个分页方法:


<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);


注意:要想使用mp中的分页功能,就必须需要安装分页插件,否则不会生效!


step1:编写一个mp的配置类,在该配置类中添加分页插件


@Configuration
@MapperScan("com.changlu.mybatisplusexer.mapper")  //使用了分配类,即可将启动器的自动打包放置在这里
public class MybatisPlusConfig {
    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));  //设置方言为MySQL
        return interceptor;
    }
}



实操


数据库中有四条记录,我们来对其进行测试:



@SpringBootTest
class MybatisplusexerApplicationTests {
    @Autowired
    private UserService userService;
    @Test
    public void saveOrUpdate() throws JsonProcessingException {
        //当前页与每页数量
        IPage<User> page = new Page<>(1,2);
        //分页查询       
        IPage<User> pageResult = userService.page(page);
        //对象转JSON字符串
        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(pageResult);
        System.out.println(json);
    }
}




可以看到查询了两条sql,一个是查询数量,另一个是进行limit查询操作!


为了方便查看Page的相关属性,我们将其转为JSON字符串并且借助工具网站来美化显示其中的内容:



records:分页查询的记录结果。

total:总记录数。

size:每页显示条数,根据初始定义的Page决定。

current:当前页。

pages:总共2页。

这样的结果内容,对于前台简直不要太舒服了!!!



3.2、XML 自定义分页


前提准备 XML 自定义分页


对于我们自定义sql语句,也就是书写xml也可以实现自定义分页!


在mp中我们无需指定mapper位置,因为对应springboot启动器已经为我们设置默认mapper读取位置:



若是我们想要修改mapper映射配置的位置,直接在yml配置中进行配置即可:


mybatis-plus:
  mapper-locations: classpath*:/mapperxxx/**/*.xml


<br/0


实操



直接在resources下的mapper文件夹中编写xml配置文件:


<?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.changlu.mybatisplusexer.mapper.UserMapper">
    <select id="queryByAge" resultType="com.changlu.mybatisplusexer.pojo.User">
        select * from Blog where age = #{age}
    </select>
</mapper>


若是想要对xml的查询结果进行分页,那么只需要在mapper中接口返回值以及属性中设置即可!


public interface UserMapper extends BaseMapper<User> {
  //此时就会根据我们传入的page来进行对结果进行分页返回
    IPage<User> queryByAge(Page<?> page,Integer age);
}


测试一下:


@Resource
private UserMapper userMapper;
@Test
public void saveOrUpdate() throws JsonProcessingException {
    //当前页与每页数量
    Page<User> page = new Page<>(1,1);
    IPage<User> userIPage = userMapper.queryByAge(page, 22);
    String json = new ObjectMapper().writeValueAsString(userIPage);
    System.out.println(json);
}



根据设置的Page信息,查询出来的分页内容与实际情况符合,分页完成!




3.3、第三方插件:PageHelper


原理分析


底层使用了一个PageInterceptor分页拦截器


PageHelper文档


提前准备


引入依赖:


<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency>


注意一下:若是你同时引入mybatis-plus以及pagehelper启动器依赖,运行时就会报异常如下。



如何解决呢?将对应pagehelper启动器中的指定mybatis依赖移除即可。


<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </exclusion>
    </exclusions>
</dependency>
</dependencies>



实操


主要就是test方法中的第1以及第3行,即可实现分页效果!


@GetMapping("/")
public ResultBody test(@RequestParam("pagenum")Integer pageNum,@RequestParam("pagesize")Integer pageSize){
    PageHelper.startPage(pageNum,pageSize);//设置起始页以及每页数量  
    List<User> users = userMapper.selectList(null);//此时底层对于select就是进行分页来得到的结果集
    PageInfo<User> userPageInfo = new PageInfo<>(users);//封装PageInfo对象
    return ResultBody.success(userPageInfo);
}



最终拿到的返回值对象:其中包含了很多的关于分页的属性,前端判断就更加容易了




相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
204 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
3月前
|
Java 关系型数据库 数据库连接
mybatis-plus学习
MyBatis-Plus ,MyBatis 最佳搭档,只做增强不做改变,为简化开发、提高效率而生。
51 5
|
4月前
|
安全 Java 数据库连接
后端框架的学习----mybatis框架(3、配置解析)
这篇文章详细介绍了MyBatis框架的核心配置文件解析,包括环境配置、属性配置、类型别名设置、映射器注册以及SqlSessionFactory和SqlSession的生命周期和作用域管理。
后端框架的学习----mybatis框架(3、配置解析)
|
4月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
4月前
|
Java 数据库连接 测试技术
后端框架的学习----mybatis框架(8、lombok)
这篇文章介绍了如何在MyBatis框架中使用lombok库来简化Java实体类的编写,包括在IDEA中安装Lombok插件、在项目中导入lombok依赖以及在实体类上使用Lombok提供的注解。
|
4月前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
4月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(5、分页)
这篇文章介绍了如何在MyBatis框架中实现分页功能,包括使用SQL的`limit`语句进行分页和利用MyBatis的`RowBounds`对象进行分页的方法。
|
4月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。
|
7月前
|
SQL Java 数据库连接
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
|
6月前
|
Java 数据库连接 Maven
Mybatis学习
Mybatis学习
31 0
下一篇
DataWorks