本文共 6708 字,大约阅读时间需要 22 分钟。
mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为java 对象并返回。
采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作
mybatis的环境搭建
第一步:创建maven工程并导入坐标 第二步:创建实体类和dao的接口 第三步:创建Mybatis的主配置文件 SqlMapConifg.xml 第四步:创建映射配置文件 IUserDao.xml
注意事项:
1、 mybatis的映射配置文件位置必须和dao接口的包结构相同
2、映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名 3、映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
1、导入依赖:
注意:Mybatis依赖不能导入springboot的mybatis,因为springboot的mybatis依赖读取数据源的位置是在application.properties配置文件。而现在我们是要手动加载Mybatis.xml配置文件中的数据源与其它参数属性,只需要引入mybatis依赖即可
mysql mysql-connector-java 5.1.38 org.mybatis mybatis 3.4.6 log4j log4j 1.2.12 junit junit 4.12 test
2、创建实体类User(略)
3、创建接口IUserMapper:(请注意:接口名称和Mapper.xml文件名称最好相同)
package com.itheima.day02_eesy01_mybatiscrud.dao;import com.itheima.day02_eesy01_mybatiscrud.domain.QueryVo;import com.itheima.day02_eesy01_mybatiscrud.domain.User;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import java.util.List;/** * @author Huangyt * @version 1.0 * @date 2020/5/12 17:13 * 用户持久层接口 */public interface IUserMapper { ListfindAll(); public void saveUser(User user); public void updateUser(User user); public void deleteUser(int id); public User findById(Integer id); //模糊查询 public List findByName(String username); //查询总数 public int findTotal(); //根据queryVo中的条件查询用户(多条件查询写法一) public List findUserByVo(QueryVo vo); //根据多个参数条件查询用户(多条件查询写法二, 此写法在Mapper.xml中不用指定parameterType) public List findUserByNameAndAddress(@Param("username") String username, @Param("address") String address);}
4、创建SqlMapConfig.xml文件,配置Mybatis环境(事务、数据库连接用户名&密码、Mapper文件)
注意:SqlMapConfig.xml配置文件和application.properties(yml)的 url 配置格式不一样application.properties(yml)的 url 配置格式
jdbc:mysql://localhost:3306/abc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
SqlMapConfig.xml的 url 配置格式(将连接符 & 替换成 amp;)
5、创建对应UserDao接口的IUserMapper.xml配置文件:(请注意:接口名称和Mapper.xml文件名称最好相同)**
select last_insert_id() insert into user (username,address,sex,birthday) values (#{username}, #{address}, #{sex}, #{birthday})update user set username=#{username}, address=#{address}, sex=#{sex}, birthday=#{birthday} where id=#{id} delete from user where id = #{id}
6、测试:
@SpringBootTestclass Day02Eesy01MybatiscrudApplicationTests { private InputStream resourceAsStream; private SqlSession sqlSession; private IUserMapper mapper; @BeforeEach //用于在测试方法执行之前执行 public void init() throws IOException { System.out.println("执行init"); //1、读取配置文件,生成字节输入流 resourceAsStream = Resources.getResourceAsStream("MybatisConfig.xml"); //2、获取SqlSessionFactory对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream); //3、获取SqlSession对象 sqlSession = sqlSessionFactory.openSession(); //4、获取Dao的代理对象 mapper = sqlSession.getMapper(IUserMapper.class); } @AfterEach//用于在测试方法执行之后执行 public void destroy() throws IOException { System.out.println("执行destroy"); //使用sqlSession进行事务提交 sqlSession.commit(); //释放资源 sqlSession.close(); resourceAsStream.close(); } @Test void contextLoads() throws IOException { Listall = mapper.findAll(); for(User user : all){ System.out.println(user); } } }
1、Mapper.xml方式:
扫描Mybatis.xml的mappers标签时找到resource属性然后解析Mapper.xml获取namespace、SQL语句、
方法名id,将多个< Select >标签语句的属性封装成Map< String, Mapper>
2、注解方式:
扫描Mybatis.xml的mappers标签时找到class属性然后解析Dao接口,扫描是否有@Select注解并获取其
中的SQL语句,再利用反射获取返回结果类型,方法名,该类的全名包路径,封装成Map< String,
Mapper>
Mapper.xml方式和注解方式的共同作用就是获取方法的SQL语句和方法名,再将其封装成Map。后面的
获取Dao接口代理,利用动态代理机制,动态获取到代理类调用的方法名和参数,利用方法名获取SQL语句和返回类型信息,最后执行SQL语句的过程(原生JDBC+反射封装返回结果)都是一模一样的!
执行MyBatis过程使用Mapper.xml方式和注解方式的图解:
我们可以概括一下当Mybatis框架使用Mapper.xml方式或注解方式执行SQL语句的过程:
1、通过 Resources.getResourceAsStream(“SqlMapConfig.xml”) 扫描Mybatis配置文件信息(包括连接数据库的4个属性 driver、url、username、password,还有mappers标签映射的×××Mapper.xml配置文件中的namespace、方法id、SQL语句等,把以上所有信息提取并封装到Configuration实体类中
(换一句话说,当我们扫描完SqlMapConfig.xml配置文件和×××Mapper.xml配置文件,成功将信息封装到Configuration实体类后,这两个配置文件已经没有用了。后面所要调用的信息全部在Configuration实体类中调用即可)2、把封装好的Configuration实体类传送给FactoryBuilder , FactoryBuilder 通过 build 方法又把Configuration实体类传送给SqlSessionFactory类,SqlSessionFactory类通过 openSession() 方法又把Configuration实体类传送给sqlSession类去处理。(击鼓传花,最终还是sqlSession类起主导作用呀)
3、UserDao mapper = sqlSession.getMapper(UserDao.class); 将传入的UserDao.class接口作为类加载容器,返回该代理对象。
4、执行 List all = mapper.findAll(); 时,mapper自动调用 invoke 方法获取该方法的名称和该方法所在类,即Dao接口的类路径,将以上两个字段合并形成key,然后获取Configuration实体类Map中的Mappers的SQL语句和返回结果类型信息,最后调用反射+JDBC技术实现查询数据库。
实现方法的过程:通过代理对象获取Key + JDBC + 反射获取类字段封装转载地址:http://gbern.baihongyu.com/