Mybatis框架技术总结(一)

// 我们也可以自己加载

InputStream inputStream = 类名.class.getClassLoader().getResourceAsStream(“mybatis-config.xml”);

3.2、SqlSessionFactoryBuilder


SqlSessionFactoryBuilder工厂构建器:

  • SqlSessionFactory.build(InputStream inputStream)

  • 通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象

String resource = “org/mybatis/example/mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

3.3、SqlSessionFactory


SqlSessionFactory有多个方法创建SqlSession实例,常用的有如下两个:

  • SqlSessionFactory.openSession :会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交该事务,更新操作数据才会持久化到数据库中

  • SqlSessionFactory.openSession(boolean autoCommit) : 参数为是否自动提交,如果设置为true,那么不需要手动提交事务

| 返回值 | 方法名 | 说明 |

| — | — | — |

| SqlSession | openSession() | 通过SqlSession构建者对象,并开启手动提交事务 |

| SqlSession | openSession(boolean autoCommit) | 通过SqlSession构建者对象,如果参数为true,则开启自动提交事务 |

3.4、SqlSession


SqlSession 提供了在数据库执行 SQL 命令所需的所有方法 。它还提供了事务的相关操作。

成员方法如下:

  • sqlSession.commit():提交事务

  • sqlSession.rollback():回滚事务

  • sqlSession.close():释放资源

3.5、mybatis工具类


我们通常将mybatis获取SqlSession实例封装成一个工具类

public class MybatisUtils {

private static SqlSessionFactory sqlSessionFactory;

static{

try {

// 使用Mybatis

// 第一步: 获取sqlSessionFactory对象

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

} catch (IOException e) {

e.printStackTrace();

}

}

//既然有了SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。

public static SqlSession getSqlSession(){

// SqlSession sqlSession = sqlSessionFactory.openSession();

// return sqlSession;

return sqlSessionFactory.openSession();

}

}

4、Mybatis开发方式

===============================================================================

4.0、Mybatis传统方式开发


4.0、Dao 层传统实现方式


  • 分层思想:控制层(controller)、业务层(service)、持久层(dao)。

  • 调用流程

在这里插入图片描述

4.1、Dao层代理开发方式


  • Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口)

  • 我们之前的开发规范是编写Dao接口,之后再编写实现类DaoImpl

  • 代理开发规范是编写Dao接口,之后再编写xml配置文件

Mapper 接口开发需要遵循以下规范:

  1. Mapper.xml文件中的namespace与mapper接口的全限定名相同

  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

在这里插入图片描述

4.2、参数的获取


4.2.1、一个参数

4.2.1.1、基本参数

我们可以使用#{}直接来取值,写任意名字都可以获取到参数。但是一般用方法的参数名来取。

例如:

  • 接口中方法定义如下

public interface UserDao {

User findUser(Integer id);

}

  • xml中的内容如下

select * from user where id = #{id}

  • 测试

@Test

public void findUser() throws IOException {

//定义mybatis配置文件的路径

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//获取Sqlsession对象

SqlSession sqlSession = sqlSessionFactory.openSession();

//获取UserDao实现类对象

UserDao userDao = sqlSession.getMapper(UserDao.class);

//调用方法测试

User user = userDao.findUser(2);

System.out.println(user);

//释放资源

sqlSession.close();

}

4.2.1.2、POJO

我们可以使用POJO中的属性名来获取对应的值。

例如:

  • 接口中方法定义如下

public interface UserDao {

User findByUser(User user);

}

  • xml中的内容如下

select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}

  • 测试

@Test

public void findByUser() throws IOException {

//定义mybatis配置文件的路径

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//获取Sqlsession对象

SqlSession sqlSession = sqlSessionFactory.openSession();

//获取UserDao实现类对象

UserDao userDao = sqlSession.getMapper(UserDao.class);

//调用方法测试

User byUser = userDao.findByUser(new User(2, “PDD”, 25, “上海”));

System.out.println(byUser);

//释放资源

sqlSession.close();

}

4.2.1.3、Map

我们可以使用map中的key来获取对应的值。

例如:

  • 接口中方法定义如下

public interface UserDao {

User findByMap(Map map);

}

  • xml中内容如下

select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}

  • 测试

@Test

public void findByMap() throws IOException {

//定义mybatis配置文件的路径

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//获取Sqlsession对象

SqlSession sqlSession = sqlSessionFactory.openSession();

//获取UserDao实现类对象

UserDao userDao = sqlSession.getMapper(UserDao.class);

//调用方法测试

Map map = new HashMap();

map.put(“id”,2);

map.put(“username”,“PDD”);

map.put(“age”,25);

map.put(“address”,“上海”);

User byMap = userDao.findByMap(map);

System.out.println(byMap);

//释放资源

sqlSession.close();

}

4.2.2、多个参数

Mybatis会把多个参数放入一个Map集合中,默认的key是argx和paramx这种格式。

例如:

  • 接口中方法定义如下

  • 我们一般在方法参数前使用@Param来设置参数名。

public interface UserDao {

User findByCondition(@Param(“tid”) Integer id,@Param(“username”)String username);

}

  • xml中内容如下

select * from user where id = #{tid} and username = #{username}

  • 测试

@Test

public void findByCondition() throws IOException {

//定义mybatis配置文件的路径

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//获取Sqlsession对象

SqlSession sqlSession = sqlSessionFactory.openSession();

//获取UserDao实现类对象

UserDao userDao = sqlSession.getMapper(UserDao.class);

//调用方法测试

User pdd = userDao.findByCondition(2, “PDD”);

System.out.println(pdd);

//释放资源

sqlSession.close();

}

4.2.3、总结

  • 建议如果只有一个参数的时候不用做什么特殊处理。

  • 如果是有多个参数的情况下一定要加上@Param来设置参数名。

4.2.4、获取参数时 #{}和${}的区别

  • 如果使用#{}.他是预编译的sql可以防止SQL注入攻击

  • 如果使用${}他是直接把参数值拿来进行拼接,这样会有SQL注入的危险

5、CRUD操作

==========================================================================

5.1、select


select 语句有很多属性可以详细配置每一条SQL语句

  • id: 就是对应的namespace中的方法名

  • resultType: Sql语句执行的返回值【完整的类名或者别名】

  • parameterType:传入SQL语句的参数类型

示例

  1. 在UserMapper中添加对应方法

public interface UserMapper {

// 查询全部用户

List getUserList();

}

  1. 在UserMapper.xml中添加Select语句

select * from mybatis.user;

  1. 在测试类中测试

public void test(){

//第一步:获得SqlSession对象

SqlSession sqlSession = MybatisUtils.getSqlSession();

//方式一:执行SQL

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

List userList = userDao.getUserList();

for (User user : userList) {

System.out.println(user);

}

// 关闭SqlSession

sqlSession.close();

}

示例2:根据id查询用户

  1. 在UserMapper中添加对应方法

public interface UserMapper {

// 根据ID查询用户

User getUserById(int id);

}

  1. 在UserMapper.xml中添加Select语句

select * from mybatis.user where id = #{id}

  1. 在测试类中测试

@Test

public void getUserById(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

User user = mapper.getUserById(1);

System.out.println(user);

sqlSession.close();

}

5.2、insert


需求:给数据库增加一个用户

  1. 在UserMapper接口中添加对应的方法

public interface UserMapper{

// insert

int addUser(User user);

}

  1. 在UserMapper.xml中添加insert语句

insert into mybatis.user(id, name, pwd) VALUES (#{id},#{name},#{pwd})

  1. 在测试类中测试

// 增删改需要提交事务

@Test

public void addUser(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

int res = mapper.addUser(new User(5, “哈哈2”, “1234”));

if(res > 0) {

System.out.println(“插入成功”);

}

// 提交事务

sqlSession.commit();

sqlSession.close();

}

  • 在插入操作中,使用parameterType属性指定要插入的数据类型

  • Sql语句中使用#{实体属性名}方式引用实体中的属性值

  • 增、删、改操作涉及数据库数据变化,所以要使用sqlSession对象显式的提交事务,即sqlSession.commit()

5.3、update


需求:修改用户的信息

  1. 在UserMapper接口中添加对应的方法

public interface UserMapper{

// 修改用户

int updateUser(User user);

}

  1. 在UserMapper.xml中添加update语句

update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id};

  1. 在测试类中测试

@Test

public void updateUser(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

int res = mapper.updateUser(new User(4, “呵呵”, “123123”));

if(res > 0){

System.out.println(“修改成功”);

}

sqlSession.commit();

sqlSession.close();

}

5.4、delete


需求:根据id删除一个用户

  1. 在UserMapper接口中添加对应的方法

public interface UserMapper{

// 删除一个用户

int deleteUser(int id);

}

  1. 在UserMapper.xml中添加update语句

delete from mybatis.user where id = #{id}

  1. 在测试类中测试

@Test

public void deleteUser(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

int res = mapper.deleteUser(4);

if(res > 0){

System.out.println(“删除成功”);

}

sqlSession.commit();

sqlSession.close();

}

5.5、万能Map


假设我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!

5.5.1、select

  1. 在Us

需要文中资料的朋友,可以加我\/信获取:vip1024b 备注Java

erMapper中添加对应方法

public interface UserMapper{

// 万能的map

User getUserById2(Map<String,Object> map);

}

  1. 在UserMapper.xml中添加insert语句

select * from mybatis.user where id = #{helloid} and name = #{name};

  1. 在测试类中测试

@Test

public void getUserById2(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

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

map.put(“helloId”,1);

sqlSession.close();

}

  • Map传递参数,直接在sql中取出key即可!

5.5.2、insert

  1. 在UserMapper中添加对应方法

public interface UserMapper{

// 万能的map

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

}

  1. 在UserMapper.xml中添加insert语句

insert into mybatis.user(id, name, pwd) VALUES (#{id},#{name},#{pwd})

  1. 在测试类中测试

// 传递map的key

@Test

public void addUser2(){

SqlSession sqlSession = MybatisUtils.getSqlSession();

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

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

map.put(“id”,5);

map.put(“name”,“啦啦啦”);

map.put(“pwd”,“123456”);

sqlSession.close();

}

  • 对象传递参数,直接在sql中取对象的属性即可!

6、动态SQL

=========================================================================

在实际开发中的SQL语句没有之前的这么简单,很多时候需要根据传入的参数情况动态的生成SQL语句。Mybatis提供了动态SQL相关的标签让我们使用。

6.1、if标签


可以使用if标签进行条件判断,条件成立才会把if标签中的内容拼接进sql语句中。

例如:

select * from user

where id = #{id}

and username = #{username}

  • 如果参数username为null则执行的sql为:select * from user where id = ?

  • 如果参数username不为null则执行的sql为:select * from user where id = ? and username = ?

  • 注意:在test属性中表示参数的时候不需要写#{},写了会出问题。

6.2、trim标签


可以使用该标签动态的添加前缀或后缀,也可以使用该标签动态的消除前缀。

注意:trim标签其实在真正开发中不会太用到,主要是为了理解后面的where标签,所以这里理解即可

6.2.1、prefixOverridess属性

用来设置需要被清除的前缀,多个值可以用|分隔,注意|前后不要有空格。例如: and|or

例如:

select * from user

and

最终执行的sql为: select * from user

6.2.2、suffixOverrides属性

用来设置需要被清除的后缀,多个值可以用|分隔,注意|前后不要有空格。例如: and|or

select * from user

where 1=1 like

最终执行的sql为: select * from user 去掉了后缀like

6.2.3、prefix属性

用来设置动态添加的前缀,如果标签中有内容就会添加上设置的前缀

select * from user

1=1

最终执行的sql为:select * from user where 1=1 动态增加了前缀where

6.2.4、 suffix属性

​ 用来设置动态添加的后缀,如果标签中有内容就会添加上设置的后缀

select * from user

where

最终执行的sql为:select * from user where 1=1 动态增加了后缀1=1

6.2.5、trim综合使用

动态添加前缀where 并且消除前缀and或者or

select * from user

id = #{id}

and username = #{username}

  • 调用方法时如果传入的id和username为null则执行的SQL为:select * from user

  • 调用方法时如果传入的id为null,username不为null,则执行的SQL为:select * from user where username = ?

6.3、where


where标签等价于:动态添加前缀where 并且消除前缀and或者or

可以使用where标签动态的拼接where并且去除前缀的and或者or。

例如:

select * from user

id = #{id}

and username = #{username}

  • 如果id和username都为null,则执行的sql为:**select * from user **

  • 如果id为null,username不为null,则执行的sql为:**select * from user where username = ? **

6.4、set


set标签等价于:动态添加前缀set 并且清除后缀逗号

可以使用set标签动态的拼接set并且去除后缀的逗号。

例如:

UPDATE USER

username = #{username},

age = #{age},

address = #{address},

where id = #{id}

如果调用方法时传入的User对象的id为2,username不为null,其他属性都为null则最终执行的sql为:UPDATE USER SET username = ? where id = ?

6.5、foreach


可以使用foreach标签遍历集合或者数组类型的参数,获取其中的元素拿来动态的拼接SQL语句。

例如:

  1. 在接口中定义方法

public interface UserDao{

List findByIds(@Param(“ids”) Integer[] ids);

}

如果期望动态的根据实际传入的数组的长度拼接SQL语句。例如传入长度为4个数组最终执行的SQL为:

select * from User WHERE id in( ? , ? , ? , ?, ? )

则在xml映射文件中可以使用以下写法

select * from User

#{id}

collection:表示要遍历的参数。

open:表示遍历开始时拼接的语句

item:表示给当前遍历到的元素的取的名字

separator:表示每遍历完一次拼接的分隔符

close:表示最后一次遍历完拼接的语句

注意:如果方法参数是数组类型,默认的参数名是array,如果方法参数是list集合默认的参数名是list。建议遇到数组或者集合类型的参数统一使用@Param注解进行命名。

6.6、choose、when、otherwise


当我们不想使用所有的条件,而只是想从多个条件中选择一个使用时。可以使用choose系列标签。类似于java中的switch。

例如:

  1. 接口中方法定义如下

public interface UserDao{

List selectChose(User user);

}

期望:

​ 如果user对象的id不为空时就通过id查询。

​ 如果id为null,username不为null就通过username查询。

​ 如果id和username都会null就查询id为3的用户

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

蚂蚁金服5面,总结了49个面试题,遇到的面试官都是P7级别以上

法时传入的User对象的id为2,username不为null,其他属性都为null则最终执行的sql为:UPDATE USER SET username = ? where id = ?

6.5、foreach


可以使用foreach标签遍历集合或者数组类型的参数,获取其中的元素拿来动态的拼接SQL语句。

例如:

  1. 在接口中定义方法

public interface UserDao{

List findByIds(@Param(“ids”) Integer[] ids);

}

如果期望动态的根据实际传入的数组的长度拼接SQL语句。例如传入长度为4个数组最终执行的SQL为:

select * from User WHERE id in( ? , ? , ? , ?, ? )

则在xml映射文件中可以使用以下写法

select * from User

#{id}

collection:表示要遍历的参数。

open:表示遍历开始时拼接的语句

item:表示给当前遍历到的元素的取的名字

separator:表示每遍历完一次拼接的分隔符

close:表示最后一次遍历完拼接的语句

注意:如果方法参数是数组类型,默认的参数名是array,如果方法参数是list集合默认的参数名是list。建议遇到数组或者集合类型的参数统一使用@Param注解进行命名。

6.6、choose、when、otherwise


当我们不想使用所有的条件,而只是想从多个条件中选择一个使用时。可以使用choose系列标签。类似于java中的switch。

例如:

  1. 接口中方法定义如下

public interface UserDao{

List selectChose(User user);

}

期望:

​ 如果user对象的id不为空时就通过id查询。

​ 如果id为null,username不为null就通过username查询。

​ 如果id和username都会null就查询id为3的用户

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

[外链图片转存中…(img-DNk8PhAY-1716311244193)]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值