MyBatis系列第2篇:入门篇,带你感受一下mybatis独特的魅力!

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

<![CDATA[ AND `id` = #{id} ]]> <![CDATA[ DELETE FROM `t_user` ]]> <![CDATA[ AND `id` = #{id} ]]> <![CDATA[ SELECT ]]> <![CDATA[ ${item} ]]> <![CDATA[ `id`, `name`, `age`, `salary` ]]> <![CDATA[ FROM `t_user` a ]]> <![CDATA[ AND a.`id` = #{id} ]]> <![CDATA[ AND a.`id` IN ]]> <![CDATA[ #{item} ]]> <![CDATA[ AND a.`name` = #{name} ]]> <![CDATA[ AND a.`age` = #{age} ]]> <![CDATA[ AND a.`salary` = #{salary} ]]> <![CDATA[ AND a.`name` like '%${nameLike}%' ]]> <![CDATA[ AND a.`salary` >= #{salaryGte} ]]> <![CDATA[ order by ${sort} ]]> <![CDATA[ LIMIT #{skip},#{pageSize} ]]>
mybatis-config.xml

chat01/src/main/resources目录中新建mybatis-config.xml,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
UserMapper接口

package com.javacode2018.mybatis.chat01;

import java.util.List;

import java.util.Map;

/**

* 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!

*/

public interface UserMapper {

/**

* 插入用户信息

* @param userModel

* @return

*/

void insert(UserModel userModel);

/**

* 批量插入用户信息

* @param userModelList

*/

void insertBatch(List userModelList);

/**

* 更新用户信息

* @param userModel

* @return

*/

int update(UserModel userModel);

/**

* 通过map来更新用户记录

* @param map

* @return

*/

int updateByMap(Map<String, Object> map);

/**

* 通过map来删除用户记录

* @param map

* @return

*/

int delete(Map<String, Object> map);

/**

* 查询用户列表

* @param map

* @return

*/

List getModelList(Map<String, Object> map);

}

UserModel类

package com.javacode2018.mybatis.chat01;

import lombok.*;

/**

* 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!

*/

@Getter

@Setter

@NoArgsConstructor

@AllArgsConstructor

@Builder

@ToString

public class UserModel {

private Long id;

private String name;

private Integer age;

private Double salary;

}

这个类上面的注解都是都是lombok中的,通过这些注解,lombok可以帮助我们自动生成上面4个字段的get方法、set方法、无参构造方法、有参有参构造方法、builder模式构建对象的代码、重写toString方法,这些都在代码编译为字节码之前会写进去,通过lombok代码是不是精简了很多,最后生成的代码大家可以反编译一下UserModel.class去看一下,感受一下,此处我们就不贴出来了。

UserUtil类

package com.javacode2018.mybatis.chat01;

import lombok.extern.slf4j.Slf4j;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**

* 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!

*/

@Slf4j

public class UserUtil {

private static SqlSessionFactory sqlSessionFactory = build();

public static SqlSessionFactory build() {

try {

return new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(“mybatis-config.xml”));

} catch (IOException e) {

log.error(e.getMessage(), e);

throw new RuntimeException(e);

}

}

@FunctionalInterface

public interface SessionCall {

O call(SqlSession session) throws Exception;

}

@FunctionalInterface

public interface MapperCall<T, O> {

O call(T mapper) throws Exception;

}

public static <T, O> O callMapper(Class tClass, MapperCall<T, O> mapper) throws Exception {

return call(session -> mapper.call(session.getMapper(tClass)));

}

public static  O call(SessionCall sessionCall) throws Exception {

try (SqlSession session = sqlSessionFactory.openSession(true)😉 {

return sessionCall.call(session);

}

}

}

创建单元测试类UserMapperTest

chat01\src\test\java\com\javacode2018\mybatis\chat01中创建UserMapperTest,代码如下:

package com.javacode2018.mybatis.chat01;

import lombok.extern.slf4j.Slf4j;

import org.junit.Test;

import java.util.*;

import java.util.stream.Collectors;

/**

* 公众号:路人甲Java,工作10年的前阿里P7分享Java、算法、数据库方面的技术干货!坚信用技术改变命运,让家人过上更体面的生活!

*/

@Slf4j

public class UserMapperTest {

//动态插入

@Test

public void insert() throws Exception {

UserModel userModel1 = UserModel.builder().name(“路人甲Java”).build();

UserUtil.callMapper(UserMapper.class, mapper -> {

mapper.insert(userModel1);

return null;

});

log.info(“插入结果:{}”, this.getModelById(userModel1.getId()));

log.info(“---------------------”);

UserModel userModel2 = UserModel.builder().name(“路人”).age(30).salary(50000.00).build();

UserUtil.callMapper(UserMapper.class, mapper -> {

mapper.insert(userModel2);

return null;

});

log.info(“插入结果:{}”, this.getModelById(userModel2.getId()));

}

//批量插入

@Test

public void insertBatch() throws Exception {

List userModelList = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

userModelList.add(UserModel.builder().name(“路人甲Java-” + i).age(30 + i).salary(10000.00 * i).build());

userModelList.add(UserModel.builder().name(“javacode2018-” + i).age(30 + i).salary(10000.00 * i).build());

}

UserUtil.callMapper(UserMapper.class, mapper -> {

mapper.insertBatch(userModelList);

return null;

});

List userModelList1 = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(null));

log.info(“结果:{}”, userModelList1);

}

//根据用户id删除数据

@Test

public void delete() throws Exception {

Map<String, Object> map = new HashMap<>();

//需要删除的用户id

map.put(“id”, 1);

Integer count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.delete(map));

log.info(“删除行数:{}”, count);

}

//动态更新

@Test

public void update() throws Exception {

//将userId=2的name修改为:路人

Long userId1 = 2L;

Integer count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.update(UserModel.builder().id(userId1).name(“ready”).build()));

log.info(“更新行数:{}”, count);

log.info(“---------------------”);

//将userId=3的name修改为:路人,薪水为:1000.88

Long userId2 = 3L;

count = UserUtil.callMapper(UserMapper.class, mapper -> mapper.update(UserModel.builder().id(userId2).name(“ready”).salary(1000.88D).build()));

log.info(“更新行数:{}”, count);

}

//按用户id查询

public UserModel getModelById(Long userId) throws Exception {

//查询指定id的数据

Map<String, Object> map = new HashMap<>();

map.put(“id”, userId);

return UserUtil.callMapper(UserMapper.class, mapper -> {

List userModelList = mapper.getModelList(map);

if (userModelList.size() == 1) {

return userModelList.get(0);

}

return null;

});

}

//查询所有数据

@Test

public void getModelList1() throws Exception {

List userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(null));

log.info(“结果:{}”, userModelList);

}

//查询多个用户id对应的数据

@Test

public void getModelListByIds() throws Exception {

List idList = Arrays.asList(2, 3, 4).stream().collect(Collectors.toList());

Map<String, Object> map = new HashMap<>();

map.put(“idList”, idList);

List userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));

log.info(“结果:{}”, userModelList);

}

//多条件 & 指定返回的列

@Test

public void getModelList2() throws Exception {

//查询姓名中包含路人甲java以及薪资大于3万的用户id、姓名

Map<String, Object> map = new HashMap<>();

map.put(“nameLike”, “路人甲java”);

map.put(“salaryGte”, 30000.00D);

//需要返回的列

List tableColumnList = new ArrayList<>();

tableColumnList.add(“id”);

tableColumnList.add(“name”);

map.put(“tableColumnList”, tableColumnList);

List userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));

log.info(“结果:{}”, userModelList);

}

//条件过滤 & 排序 & 分页查询数据 & 只返回用户id、salary

@Test

public void getPage() throws Exception {

//查询姓名中包含路人甲java以及薪资大于3万的用户id,按照薪资倒叙,每页5条取第1页

Map<String, Object> map = new HashMap<>();

map.put(“nameLike”, “路人甲java”);

map.put(“salaryGte”, 30000.00D);

//加入排序参数

map.put(“sort”, “salary desc”);

//加入分页参数

int page = 1;

int pageSize = 5;

map.put(“skip”, (page - 1) * pageSize);

map.put(“pageSize”, pageSize);

//加入需要返回的列

List tableColumnList = new ArrayList<>();

tableColumnList.add(“id”);

tableColumnList.add(“salary”);

map.put(“tableColumnList”, tableColumnList);

List userModelList = UserUtil.callMapper(UserMapper.class, mapper -> mapper.getModelList(map));

log.info(“结果:{}”, userModelList);

}

}

项目最终结构如下

用例:动态插入

运行UserMapperTest#insert,输出如下:

37:58.556 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==>  Preparing: INSERT INTO t_user ( name ) VALUES ( ? )

37:58.605 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==> Parameters: 路人甲Java(String)

37:58.613 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - <==    Updates: 1

37:58.641 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT idnameagesalary FROM t_user a WHERE a.id = ?

37:58.641 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 1(Long)

37:58.663 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 1

37:58.664 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 插入结果:UserModel(id=1, name=路人甲Java, age=1, salary=0.0)

37:58.667 [main] INFO  c.j.mybatis.chat01.UserMapperTest - ---------------------

37:58.668 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==>  Preparing: INSERT INTO t_user ( nameagesalary ) VALUES ( ?, ?, ? )

37:58.675 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - ==> Parameters: 路人(String), 30(Integer), 50000.0(Double)

37:58.679 [main] DEBUG c.j.mybatis.chat01.UserMapper.insert - <==    Updates: 1

37:58.681 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT idnameagesalary FROM t_user a WHERE a.id = ?

37:58.681 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 2(Long)

37:58.683 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 1

37:58.683 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 插入结果:UserModel(id=2, name=路人, age=30, salary=50000.0)

UserMapperTest#insert这个方法主要有4步操作:

步骤1:插入一条用户记录,用户记录只有name字段有值

步骤2:去db中查询步骤1中插入的记录

步骤3:插入一条用户记录,这次插入的记录所有字段都指定了值

步骤4:去db中查询步骤3中插入的记录

**重点来了:**大家认真看一下UserMapperTest#insert方法的代码,两个插入调用都是mapper.insert方法,传入的都是UserModel对象,唯一不同的是这个对象构建的时候字段的值不一样,最后再认真看一下上面输出的sql,产生的2个insert也是不一样的,这个mapper.insert方法可以根据UserModel对象字段是否有值来组装我们需要的sql,是不是很牛逼,这就是动态插入。

用例:批量插入

运行UserMapperTest#insertBatch,输出如下:

38:12.425 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - ==>  Preparing: INSERT INTO t_user (idnameagesalary) VALUES (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?)

38:12.476 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - ==> Parameters: null, 路人甲Java-1(String), 31(Integer), 10000.0(Double), null, javacode2018-1(String), 31(Integer), 10000.0(Double), null, 路人甲Java-2(String), 32(Integer), 20000.0(Double), null, javacode2018-2(String), 32(Integer), 20000.0(Double), null, 路人甲Java-3(String), 33(Integer), 30000.0(Double), null, javacode2018-3(String), 33(Integer), 30000.0(Double), null, 路人甲Java-4(String), 34(Integer), 40000.0(Double), null, javacode2018-4(String), 34(Integer), 40000.0(Double), null, 路人甲Java-5(String), 35(Integer), 50000.0(Double), null, javacode2018-5(String), 35(Integer), 50000.0(Double)

38:12.484 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - <==    Updates: 10

38:12.502 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT idnameagesalary FROM t_user a

38:12.502 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters:

38:12.521 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 12

38:12.521 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 结果:[UserModel(id=1, name=路人甲Java, age=1, salary=0.0), UserModel(id=2, name=路人, age=30, salary=50000.0), UserModel(id=3, name=路人甲Java-1, age=31, salary=10000.0), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0), UserModel(id=5, name=路人甲Java-2, age=32, salary=20000.0), UserModel(id=6, name=javacode2018-2, age=32, salary=20000.0), UserModel(id=7, name=路人甲Java-3, age=33, salary=30000.0), UserModel(id=8, name=javacode2018-3, age=33, salary=30000.0), UserModel(id=9, name=路人甲Java-4, age=34, salary=40000.0), UserModel(id=10, name=javacode2018-4, age=34, salary=40000.0), UserModel(id=11, name=路人甲Java-5, age=35, salary=50000.0), UserModel(id=12, name=javacode2018-5, age=35, salary=50000.0)]

这次批量插入了10条用户记录,可以看到有这样的输出:

40:40.727 [main] DEBUG c.j.m.chat01.UserMapper.insertBatch - <==    Updates: 10

上面这个表示插入影响的行数,10表示插入了10行。

批量插入之后,又执行了全表查询,这次插入了10条,加上前面的2个单条插入,表中总计12条记录。

用例:根据用户id删除数据

运行UserMapperTest#delete,输出如下:

38:36.498 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - ==>  Preparing: DELETE FROM t_user WHERE id = ?

38:36.551 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - ==> Parameters: 1(Integer)

38:36.560 [main] DEBUG c.j.mybatis.chat01.UserMapper.delete - <==    Updates: 1

38:36.561 [main] INFO c.j.mybatis.chat01.UserMapperTest - 删除行数:1

用例:动态更新

运行UserMapperTest#update,输出如下:

38:51.289 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==>  Preparing: UPDATE t_user SET name = ? WHERE id = ?

38:51.347 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==> Parameters: ready(String), 2(Long)

38:51.355 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - <==    Updates: 1

38:51.356 [main] INFO c.j.mybatis.chat01.UserMapperTest - 更新行数:1

38:51.358 [main] INFO  c.j.mybatis.chat01.UserMapperTest - ---------------------

38:51.359 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==>  Preparing: UPDATE t_user SET name = ?, salary = ? WHERE id = ?

38:51.360 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - ==> Parameters: ready(String), 1000.88(Double), 3(Long)

38:51.363 [main] DEBUG c.j.mybatis.chat01.UserMapper.update - <==    Updates: 1

38:51.364 [main] INFO c.j.mybatis.chat01.UserMapperTest - 更新行数:1

UserMapperTest#update方法,大家也认真看一下,2个更新,调用都是mapper.update方法,传入的都是UserModel类型的参数,只是2个UserModel对象的字段值不一样,最后产生的2个update语句也是不一样的,这个update语句是mybatis动态组装的,mybatis可以根据UserModel中字段是否为NULL,来拼装sql,这个更新是不是很强大。

用例:动态查询
查询所有数据

运行UserMapperTest#getModelList1,输出如下:

39:10.552 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT idnameagesalary FROM t_user a

39:10.611 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters:

39:10.639 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 11

39:10.639 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 结果:[UserModel(id=2, name=ready, age=30, salary=50000.0), UserModel(id=3, name=ready, age=31, salary=1000.88), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0), UserModel(id=5, name=路人甲Java-2, age=32, salary=20000.0), UserModel(id=6, name=javacode2018-2, age=32, salary=20000.0), UserModel(id=7, name=路人甲Java-3, age=33, salary=30000.0), UserModel(id=8, name=javacode2018-3, age=33, salary=30000.0), UserModel(id=9, name=路人甲Java-4, age=34, salary=40000.0), UserModel(id=10, name=javacode2018-4, age=34, salary=40000.0), UserModel(id=11, name=路人甲Java-5, age=35, salary=50000.0), UserModel(id=12, name=javacode2018-5, age=35, salary=50000.0)]

可以看到sql是没有查询条件的。

查询多个用户id对应的数据

运行UserMapperTest#getModelListByIds,输出如下:

39:38.000 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT idnameagesalary FROM t_user a WHERE a.id IN ( ? , ? , ? )

39:38.064 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 2(Integer), 3(Integer), 4(Integer)

39:38.096 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3

39:38.097 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 结果:[UserModel(id=2, name=ready, age=30, salary=50000.0), UserModel(id=3, name=ready, age=31, salary=1000.88), UserModel(id=4, name=javacode2018-1, age=31, salary=10000.0)]

上面这个按照id列表查询也是比较常用的,比如我们在电商中查询订单列表,还需要查询每个订单对应的商品,此时可以先查询订单列表,然后在通过订单列表拿到所有的商品id集合,然后通过商品id集合去通过上面的方式检索商品信息,只需要2次查询就可以查询出订单及商品的信息了。

多条件 & 指定返回的列

运行UserMapperTest#getModelList2,查询姓名中包含路人甲java以及薪资大于3万的用户id、姓名,输出如下:

41:12.185 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT id , name FROM t_user a WHERE a.name like ‘%路人甲java%’ AND a.salary >= ?

41:12.275 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 30000.0(Double)

41:12.311 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3

41:12.312 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 结果:[UserModel(id=7, name=路人甲Java-3, age=null, salary=null), UserModel(id=9, name=路人甲Java-4, age=null, salary=null), UserModel(id=11, name=路人甲Java-5, age=null, salary=null)]

看一下上面select语句,select后面只有id,name2个字段,where后面有多个条件,这种查询也是比较常用的,有些表可能有几十个字段,可能我们只需要几个字段,就可以使用上面这种查询。

条件过滤 & 排序 & 分页查询数据 & 只返回用户id、salary

运行UserMapperTest#getModelList3,查询姓名中包含路人甲java以及薪资大于3万的用户id,按照薪资倒叙,每页5条取第1页,输出如下:

44:00.719 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==>  Preparing: SELECT id , salary FROM t_user a WHERE a.name like ‘%路人甲java%’ AND a.salary >= ? order by salary desc LIMIT ?,?

44:00.775 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - ==> Parameters: 30000.0(Double), 0(Integer), 5(Integer)

44:00.805 [main] DEBUG c.j.m.chat01.UserMapper.getModelList - <==      Total: 3

44:00.806 [main] INFO  c.j.mybatis.chat01.UserMapperTest - 结果:[UserModel(id=11, name=null, age=null, salary=50000.0), UserModel(id=9, name=null, age=null, salary=40000.0), UserModel(id=7, name=null, age=null, salary=30000.0)]

大家主要看一下输出的sql,如下:

SELECT id , salary FROM t_user a WHERE a.name like ‘%路人甲java%’ AND a.salary >= ? order by salary desc LIMIT ?,?

这个sql会根据查询条件,自动构建出我们需要的sql,这点上面是最厉害的。

案例总结

上面列举的一些用例基本上包含了我们对db所需的大部分操作,动态sql处理方面体现的最为强劲,如果让我们自己写,我们需要写很多判断,而用mybatis这么简单就实现了,我们在java代码中没有看到一个判断拼接语句,而这些sql的判断拼接都在一个文件中:user.xml中,这个就是mybatis中核心的文件,我们需要写的sql及判断逻辑基本上都在这个xml中,大家可以认真去看一下这个xml文件。

mybatis开发项目的具体步骤

项目中引入mybatis maven配置

org.mybatis

mybatis

${mybatis.version}

上面的mybatis.version版本,大家可以在maven社区中央仓库中去查找最新的,目前最新的是3.5.3

创建mybatis配置文件

mybatis配置文件为xml格式,可以放在resource目录下面,如上面案例中的mybatis-config.xml,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>

这个文件主要是对mybatis进行全局配置,比如数据源、事务的配置,如上面的datasource元素用来配置数据源,数据源中就需要指定数据库的一些配置信息;还有其他更多的配置,此处先不做具体说明,后面我们慢慢来,整个系列完成之后,这些配置大家都会懂的。

创建mapper xml文件

如上面案例中的user.xml,大家在打开看看,我们需要对t_user表所有操作sql就写在这个文件中,下一篇文章我们会详细介绍mapper xml文件的各种写法,user.xml文件是对t_user表的所有操作一般都会放在这个里面,mybatis如何使用到这个文件呢,我们需要在上面的mybatis配置文件中引入这个mapper文件,如案例中在mybatis-config.xml有下面这样的内容:

mappers元素中可以有多个mapper文件,我们开发的项目中可能有很多表需要操作,那么对应会有很多mapper xml文件,我们都需要在mappers元素中进行引入,然后mybatis才会使用到。

创建Mapper接口

开发者如何去调用user.xml中的各种操作去执行sql呢,这时我们就需要一个Mapper接口了Mapper接口会和mapper xml建立映射关系,当我们调用Mapper接口中的方法的时候,会间接的调用到mapper xml中的各种数据的sql操作,Mapper接口如何和Mapper xml文件关联的呢?

大家去看一下user.xml文件中有个这样的一个配置:

注意上面的namespace的值,对应的是UserMapper这个接口完整的引用,通过这个namespace,UserMapper接口就可以user.xml建立了映射关系。

user.xml中又有很多db操作,这些操作会和UserMapper接口中的方法建立映射关系,当调用UserMapper中的方法的时候,间接的会调用到user.xml中对应的操作。

user.xml中有下面一段配置:

<![CDATA[ INSERT INTO `t_user` (`id`, `name`, `age`, `salary`) VALUES ]]>

(#{item.id}, #{item.name}, #{item.age}, #{item.salary})

UserMapper中有个insertBatch方法和上面这个insert批量插入对应,如下:

/**

* 批量插入用户信息

* @param userModelList

*/

void insertBatch(List userModelList);

所以当我们调用UserMapper中的insertBatch方法的时候,会间接调用到user.xml中的 id="insertBatch"这个操作。

提示一下:接口和mapper xml映射起来间接调用,是通过java动态代理实现的,后面我们会详解如何实现的。

下面我们就可以使用mybatis来操作db了。

通过mybatis获取Mapper接口执行对db的操作

上面我们说了,我们可以通过mapper接口来执行对db的操作,获取Mapper的主要代码如下:

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream(“mybatis-config.xml”));

SqlSession sqlSession = sqlSessionFactory.openSession(true);

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

上面代码中使用到了mybatis中的核心组件,我们具体来看一下。

Mybatis核心对象介绍
SqlSessionFactoryBuilder

这个是一个构建器,通过名字大家也可以感觉到SqlSessionFactoryBuilder构建器,是用来构建SqlSessionFactory对象的,SqlSessionFactoryBuilder可以通过读取mybatis的配置文件,然后构建一个SqlSessionFactory对象,一个项目中有很多mapper xml文件,如果每次操作都去重新解析是非常慢的,那么怎么办?

能不能第一次解析好然后放在内存中,以后直接使用,SqlSessionFactoryBuilder就是搞这个事情的,将mybatis配置文件、mapper xml文件、mapper xml文件和Mapper 接口的映射关系,这些都先给解析好,然后放在java对象中,java对象存在于内存中,内存中访问会非常快的,那么我们每次去用的时候就不需要重新去解析xml了,SqlSessionFactoryBuilder解析配置之后,生成的对象就是SqlSessionFactory,这个是一个重量级的对象,创建他是比较耗时的,所以一般一个db我们会创建一个SqlSessionFactory对象,然后在系统运行过程中会一直存在,而SqlSessionFactoryBuilder用完了就可以释放了。

SqlSessionFactory

通过名字可以知道,这个是一个工厂,是用来创建SqlSession的工厂,SqlSessionFactory是一个重量级的对象,一般一个db对应一个SqlSessionFactory对象,系统运行过程中会一直存在。

SqlSessionFactory是一个接口,这个接口有2个实现DefaultSqlSessionFactorySqlSessionManager,一般都是通过SqlSessionFactoryBuilder来创建SqlSessionFactory对象。

通过SqlSessionFactoryBuilder来创建SqlSessionFactory对象主要有2种方式,一种通过读取mybatis配置文件的方式,另外一种是硬编码的方式,这个后面会专门抽一篇文件介绍这块,springboot中会使用到硬编码的方式,所以这块会详细介绍。

SqlSession

我们通过jdbc操作数据库需要先获取一个Connection连接,然后拿着这个连接去对db进行操作,在mybatis中SqlSession就类似于jdbc中Connection连接对象,在mybatis中叫做Sql会话对象,一般我们一个db操作使用一个SqlSession对象,所以这个对象一般是方法级别的,方法结束之后,这个对象就销毁了,这个对象可以调用sqlSessionFactory.openSession的方法来进行获取。

我们可以直接通过SqlSession对象来调用mapper xml中各种db操作,需要指定具体的操作的id,id的格式为namespace.操作的id

Mapper接口

我们可以通过SqlSession直接调用mapper xml中的db操作,不过更简单的以及推荐的方式是使用Mapper接口,Mapper接口中的方法和mapper xml文件中的各种db操作建立了映射关系,是通过Mapper接口完整名称+方法名称mapper xml中的namespace+具体操作的id来进行关联的,然后我们直接调用Mapper接口中的方法就可以间接的操作db了,使用想当方便,Mapper接口需要通过SqlSession获取,传入Mapper接口对应的Class对象,然后会返回这个接口的实例,如:

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

总结

本篇文章主要通过一个案例来感受一下mybatis可以干什么,以及他的强大之处,还需要大家掌握mybatis开发项目的具体步骤,后面的文章将对mybatis中具体的知识点做详细介绍,让大家成为mybatis高手。

案例代码获取方式

扫码添加微信备注:mybatis案例,即可获取

MyBatis系列

总结

虽然面试套路众多,但对于技术面试来说,主要还是考察一个人的技术能力和沟通能力。不同类型的面试官根据自身的理解问的问题也不尽相同,没有规律可循。

上面提到的关于这些JAVA基础、三大框架、项目经验、并发编程、JVM及调优、网络、设计模式、spring+mybatis源码解读、Mysql调优、分布式监控、消息队列、分布式存储等等面试题笔记及资料

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
使用一个SqlSession对象,所以这个对象一般是方法级别的,方法结束之后,这个对象就销毁了,这个对象可以调用sqlSessionFactory.openSession的方法来进行获取。

我们可以直接通过SqlSession对象来调用mapper xml中各种db操作,需要指定具体的操作的id,id的格式为namespace.操作的id

Mapper接口

我们可以通过SqlSession直接调用mapper xml中的db操作,不过更简单的以及推荐的方式是使用Mapper接口,Mapper接口中的方法和mapper xml文件中的各种db操作建立了映射关系,是通过Mapper接口完整名称+方法名称mapper xml中的namespace+具体操作的id来进行关联的,然后我们直接调用Mapper接口中的方法就可以间接的操作db了,使用想当方便,Mapper接口需要通过SqlSession获取,传入Mapper接口对应的Class对象,然后会返回这个接口的实例,如:

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

总结

本篇文章主要通过一个案例来感受一下mybatis可以干什么,以及他的强大之处,还需要大家掌握mybatis开发项目的具体步骤,后面的文章将对mybatis中具体的知识点做详细介绍,让大家成为mybatis高手。

案例代码获取方式

扫码添加微信备注:mybatis案例,即可获取

MyBatis系列

总结

虽然面试套路众多,但对于技术面试来说,主要还是考察一个人的技术能力和沟通能力。不同类型的面试官根据自身的理解问的问题也不尽相同,没有规律可循。

[外链图片转存中…(img-IriUBaNO-1714708861082)]

[外链图片转存中…(img-llmnQSEX-1714708861082)]

上面提到的关于这些JAVA基础、三大框架、项目经验、并发编程、JVM及调优、网络、设计模式、spring+mybatis源码解读、Mysql调优、分布式监控、消息队列、分布式存储等等面试题笔记及资料

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值