MyBatis的从零到壹(mybatis工作原理)
什么是MyBits?
提到mybits,我们就得想到之前学过的JDBC,还记得我们用jdbc操作数据库时需要哪些步骤吗 1.注册驱动 2.获取连接 3.获取操作对象PrepardStatement 4.执行sql 5.处理结果 6.关闭资源 复制代码
代码在上面了,不记得的可以看一下
通过上面的jdbc我们会发现还是有很多问题存在的 1.数据库频繁的连接创建,释放资源会照成系统的资源浪费,从而影响系统的性能,如果使用数据库连接池就可以解决这个问题 2.sql语句中硬编码,照成代码不易维护,实际应用sql变化的可能性非常大,那么我们就需要更改java代码 3.使用peepardStatement向占位符传参也存在硬编码,以为后面sql语句的条件不一定,修改sql语句也是需要修改代码的,不利于维护‘ 4.对结果集解析存在硬编码(查询列名),如果列名改变也会导致代码变化,系统非常的不利于维护,如果能够将数据库记录封装成pojo对象解析会比较方便 综上所述:硬编码问题严重,步骤繁琐,sql语句不易维护 复制代码
Mybatis的介绍
mybits是一个优秀的基于java的持久层框架,它内部封装了jdbc,能够让开发者只关注sql语句本身,而不需要花费精力去处理加载驱动,获取连接这些烦琐的操作 mybits通过xml或者注解的方式将statement配置起来,并通过java对象和statement中的动态sql生成映射生成最终的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。采用了ORM思想解决了实体和数据库映射的问题,对jdbc底层进行了封装,屏蔽了jdbc api的访问细节,使我们不用与和jdbc打交道,就可以完成数据库的持久化操作 复制代码
Mybatis快速入门
1.在pom文件里使用下面的依赖 复制代码
<dependencies> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--MyBatis坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--lombok 依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> </dependency> </dependencies> 复制代码
创建数据库
USE mybatis_day01; CREATE TABLE t_user( uid int PRIMARY KEY auto_increment, username varchar(40), sex varchar(10), birthday date, address varchar(40) ); INSERT INTO `t_user` VALUES (null, 'zs', '男', '2018-08-08', '北京'); INSERT INTO `t_user` VALUES (null, 'ls', '女', '2018-08-30', '武汉'); INSERT INTO `t_user` VALUES (null, 'ww', '男', '2018-08-08', '北京'); 复制代码
创建实体类
@NoArgsConstructor @Data public class User implements Serializable { private Integer uid; private String username; private String sex; private Date birthday; private String address; } 复制代码
创建UserDao接口
/** * 查询所有的用户 */ List<User> findAll(); } 复制代码
3.2.4创建 UserDao.xml 映射文件
在创建mybatis-config.xml核心配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration> ``` 主要介绍2点,上面configuration中的配置是数据库的配置,具体的可以去mybits官网上查看 mappers标签下主要是引入上面配的UserDao.xml文件 注意:dao接口的目录一定要和映射文件的目录和名字相同 ``` 接下来我们使用测试类在测试一下 复制代码
@Test public void test01() throws IOException { //首先得到MyBatis核心文件的文件流 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); //加载配置文件,获得SqlSessionFactory对象(使用了建造者模式) SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); //获取连接对象(使用了工厂模式) SqlSession sqlSession = sqlSessionFactory.openSession(); //获取dao接口的代理对象,(使用了代理模式) UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> l = userDao.findAll(); for (User user : l) { System.out.println(user); } sqlSession.close(); resourceAsStream.close(); } 复制代码
详解核心配置文件(mybatis-config)
1.当我们需要使用数据库的配置文件时,使用properties标签,从而引入进行使用
然后在数据库的配置中使用${key}来获取配置文件中的value,例如;
2.起别名:typeAliases 我们每次写全限定类名都比较麻烦,可以给起个别名方便我们引用
这样就可以直接引用了
3.引入配置文件:Mapper 可以直接引入映文件路径,也可以通过扫描接口的方式
详解配置文件UserDao.xml
在上述代码中,我们可以发现有2个参数可能大家还很陌生
resultType介绍:
resultType从字面上看是结果类型,没错,就相当于是返回值类型 那么我们要怎么写呢?分以下几种情况 1.如果是返回简单的类型,如果是基本数据类型,直接写名字就行,int|long 如果返回的是String类型,还要写它String的全路径名 2.如果返回的是pojo对象,则直接返回对象的全类名 3.返回pojo列表,eg:返回List<User> list;返回的是一个集合,我们返回类型写该集合发泛型就好(注:在mybits中,mybatis会对数据的数量进行分析,判别,如果超过1条就会使用集合来进行封装,所以我们直接返回泛型就好) 4.返回的是Map集合类型 复制代码
这是基本类型 <select id="findCount" resultType="int"> select count(*) from t_user ; </select> String类型 <select id="findCount" resultType="java.lang.String"> select count(*) from t_user ; </select> pojo类型 <select id="findCount" resultType="com.albb.User"> select count(*) from t_user ; </select> 复制代码
ParameterType详解
1.基本类型直接写int|long,字符串直接写全限定类名 java.long.String 如果要使用传递的参数,直接写#{任意字段} ${value} 2.传递pojo对象,也是写pojo的全限定类名, 如果要使用传递参数,直接写#{对象属性名} 3.如果传递的是包装对象数据,也是使用#{}取值,取值的时候先找到属性,然后再通过属性名.属性名来找值 复制代码
<!--parameterType传递简单的参数: 1. 直接使用#{} 取值即可 2. 大括号里面一般写参数的名字,当然写什么都可以!!但是不建议这么做--> <select id="findUserByUsername" resultType="com.albb.bean.User" parameterType="java.lang.String"> select * from t_user where username = #{username} </select> 复制代码
<!--parametertype传递对象数据 1. 也是使用#{}取值 2. 大括号里面一般写javabean属性的名字。 --> <select id="findUserByUsername02" resultType="com.albb.bean.User" parameterType="com.itheima.bean.User"> <!-- select * from t_user where username = #{对象的属性名}--> select * from t_user where username = #{username} </select> 复制代码
<code class="hljs language- 1. 也是使用#{}取值 2. 取值的时候,需要先找到QueryVo里面的属性user 3. 再使用user.uid 去找到uid 的值。 --> <!--根据用户id查询用户 使用QueryVo传递参数user user对象中包含uid属性 当parameterType传递的是包装类型时,获取对应的参数#{对象属性.属性名称} --> <select id="getUserByQueryVo" parameterType="QueryVo" resultType="User"> select * from t_user where uid=#{user.uid} </select> 复制代码
当我们如果想要传递多个简单类型参数,该如何传呢? 第一种方法:把参数封装到pojo对象中去【推荐】 第二种方法:把多个简单类型封装到map集合中【map的key用的比较少】 第三种办法:直接在参数前面加上@Param注解
List<User> getUserListByNameAndAddres(@Param("username") String username,@Param("address") String address); } 复制代码
// 方式一:使用@Param注解 直接传递 #{参数名称} List<User> getList(@Param("username") String username,@Param("roleId") Integer roleId); select * from t_user where username like concat('%',#{username},'%') and roleId=#{roleId} // 方式二:封装成一个pojo对象类型 #{javabean属性名称} 【实际开发】 public class ParamVo(){ private String username; private Integer roleId; } select * from t_user where username like concat('%',#{username},'%') and roleId=#{roleId} // 方式三:封装成一个Map集合 #{map的key} Map map = new HashMap(); map.put("username","张"); map.put("roleId",3); select * from t_user where username like concat('%',#{username},'%') and roleId=#{roleId} 复制代码
扩展:当我们在进行新增操作时,怎么样才能拿到这条记录的id呢 方式一:selectKey获取主键 复制代码
方式二:通过属性配置
resultMap结果类型(当表中字段和javabean中字段不一致时需要手动进行映射配置)
1.比较简单就是在查询语句中给字段起别名,从而让他和javabean中的字段一致 2.通过resultMap映射的方式,当他们一一对应起来 复制代码
<!-- id:是resultMap的唯一表示 type:表示配置的是哪个javabean --> <resultMap id="user" type="User"> <!-- id标签配置主键列字段的映射 property:表示javabean中的属性 column:表示表中的字段 --> <id column="u_id" property="uid"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> </resultMap> 复制代码
此时我们的返回值就不能写resultTye了,应该写resultMap
<select id="findAll" resultMap="user"> SELECT *from t_user </select> 复制代码
${}和#{}的区别
1.他们都可以进行属性取值, 如果是基本类型:${value}来进行取值或者#{任意字段(推荐用属性名称)} 如果是pojo类型,${属性名称},#{属性名称} 2.#{}可以进行预编译,有效防止数据注入问题,会自动进行类型转换,一般会在字段头上加’‘,所以如果在进行模糊查询或者排序时,必须使用${} ${}只会进行sql拼接,不能防止sql注入,不会进行类型转换,在模糊查询或者排序时使用它’ 一般工作时使用#{}多一点
作者:一条小白白啊
链接:https://juejin.cn/post/7031800221571285006