1.认识mybatis能做什么?
mybatis是一款持久层框架,对jdbc进行轻量级封装,做数据库curd操作,简化jdbc的代码,避免了繁琐的设置参数与获取结果集的代码。
mybatis需要开发人员自己编写sql语句进行数据库操作。
mybatis通过xml或注解实现类到表的一一映射,类的属性到表的字段的映射。这一步称为orm对象关系映射.
简而言之一句话:就是做数据库的curd操作。需要编写sql语句。
2.了解orm框架的学习步骤
mybatis勉勉强强的称为半自动化的orm框架,因为还需要编写sql语句。使用更加灵活。对一些复杂的数据库操作实现更加方便。
mybatis-plus框架,是基于mybatis框架运行,更加趋向于纯自动化的orm框架,但仍然支持sql语句。
spring-data-jpa框架,是纯自动化的orm框架。当我们把类与表,属性与字段做完映射后,不用编写sql语句,以面向对象的方式来做数据库操作。这种方式在实际开发中使用起来对开发人员要求更加高。
公司的实际应用中,mybatis与jpa使用频繁。
3.40分钟入门案例
-
创建java项目,添加依赖项
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency>
-
创建数据库表,与对应的实体类
CREATE TABLE `sys_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `uname` varchar(50) DEFAULT NULL, `upwd` varchar(100) DEFAULT NULL, `uphone` char(11) DEFAULT NULL, `uemail` varchar(40) DEFAULT NULL, `uwechat` varchar(30) DEFAULT NULL, `usex` varchar(5) DEFAULT NULL, `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='系统管理-用户表';
-
创建mybatis风格的xml配置文件与映射文件
配置文件: <configuration> <!--配置数据库环境,支持多数据库配置--> <environments default="dev1"> <environment id="dev1"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/704a47?characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/sys/sysuser-mapper.xml"></mapper> </mappers> </configuration>
映射文件: <?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="a.b"> <select id="getById" resultType="com.javasm.sys.entity.SysUser"> select * from sys_user where id=#{azzz} </select> </mapper>
注意点:切记切记把映射文件配置到配置文件中。
-
加载xml配置文件,初始化mybatis的核心对象SqlSessionFactory
<mapper namespace="a.b"> <select id="getById" resultType="com.javasm.sys.entity.SysUser"> select * from sys_user where id=#{azzz} </select> <select id="getByUname" resultType="com.javasm.sys.entity.SysUser"> select * from sys_user where uname =#{aaaa} </select> <select id="listUsers" resultType="com.javasm.sys.entity.SysUser"> select * from sys_user </select> </mapper>
4.对mybatis代码进行分析
4.0 SqlSessionFactoryBuilder核心对象
属于设置模式中的构建者模式,一般来说此对象中都有一个build方法;此对象职责为了实例化并初始化一个复杂的单例对象。 生命周期:此对象永不作为全局变量存在,就局部变量,用完即销毁。 方法:build()
4.1 SqlSessionFactory核心对象
实现类是DefaultSqlSessionFactory,此类中有一个成员变量Configuration对象,这个对象是mybatis最最重要的一个配置对象,此配置对象与配置文件,映射文件息息相关。 其实这个sqlSessionFactory对象并不重要,它只是一层外壳,对Configuration进行包装了。 生命周期:全局唯一的单例对象。创建出来就不销毁,直到程序进程关闭。 方法:openSession方法。
4.2 Configuration对象(重要)
影响后续ssm整合学习,影响mybatis向springboot整合的学习
第一个重要属性:Environment属性,是数据库连接池,事务管理,id。 第二个重要属性:mappedStatemetns的Map集合,此集合用来封装对映射文件中的curd标签的解析结果。 生命周期:全局唯一,贯穿mybatis整体。属于最重要对象。 第三个属性:typeAliasRegistry类型别名注册器对象,是个Map,默认有很多内嵌别名: hashMap String int double
4.3 SqlSession核心对象
实现类:DefaultSqlSession会话对象,用来执行数据库curd操作,有selectOne,selecList,insert,delete,update等方法。 生命周期:很短暂的,随用随创建,用完即销毁。绝对不会是全局,静态。 方法: selectOne selectList insert update delete getMapper(这个最重要)
5.认识mybatis的xml风格的配置文件(不重要)
1.environments标签配置数据库环境,启用事务管理,启用连接池。 2.mappers标签配置映射文件。 3.properties引用外部properties资源配置文件 4.settings标签,用来改变mybatis的默认运行行为的。 <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> <setting name="mapUnderscoreToCamelCase" value="true"/></setting> </settings> 5.typeAilas别名标签 <!--类型别名标签--> <typeAliases> <!--对指定包下的类全部自动注册别名,类名首字母小写;其实别名是忽略大小写,注意:千万出现同名的类--> <package name="com.javasm"></package> <!--<typeAlias type="com.javasm.sys.entity.Sysuser" alias="suser"></typeAlias>--> </typeAliases> mybatis默认提供了常用类的内嵌别名:string,int,map,list等
6.认识mybatis的xml风格的映射文件
注意一点:mapper标签的namespace属性,必须有值,而且多个映射文件的namespace不能重复。
6.1 curd操作
insert,update,delete标签,都没有resultType属性。
<!-- 如果我们传入的参数是个简单类型(String,int,date),#{随便写},因为mybatis底层判断传入的参数是简单类型,则执行把参数作为动态参数赋值。 如果我们传入的参数是个实体类,#{属性名},因为mybaits底层会把属性名首字母大写,参数.getDname得到动态参数。 --> <!-- 如果数据库表主键自增,需要获取新插入记录的主键,使用useGeneratedKeys="true" keyProperty="id",实际应用中,只有数据量偏小的项目,采用主键自增。 如果数据库表主键是自己设置,无需考虑获取新增记录主键。 --> <insert id="save" useGeneratedKeys="true" keyProperty="id"> insert into sys_dept(dname,daddress) values(#{dname},#{daddress}) </insert>
@Test public void test4_updateById2() throws IOException { InputStream in= Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory f = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = f.openSession();//这里打开的会话对象,默认是启用事务控制,对insert,update。delete操作不会自动提交数据库 Map<String,Object> map = new HashMap<String, Object>(); map.put("n","市场三部"); map.put("a","aaaaaa"); map.put("id",4); int r = sqlSession.update("com.javasm.sys.sysdeptDao.updateById2", map); sqlSession.commit(); sqlSession.close(); } <update id="updateById2"> update sys_dept set dname=#{n},daddress=#{a} where id=#{id} </update>
<delete id="delById"> delete from sys_dept where id=#{id} </delete>
6.2动态参数获取
在映射文件中编写sql语句,需要动态参数支持两张写法,#{}或${}. #{}:mybatis对#{}进行sql解析时,会把解析称为?占位符到sql语句中,然后PreparedStatement进行sql编译,set动态参数。有效避免sql注入攻击。 简单类型参数,#{随便写},因为mybatis底层判断传入的参数是简单类型,则执行把参数作为动态参数赋值。 实体类参数,#{属性名},因为mybaits底层会把属性名首字母大写,参数.getDname得到动态参数。 map参数,#{key} ${}:mybatis对${}进行解析时,会直接把动态参数拼接到sql语句中.只有一种情况才使用${}获取动态参数. 动态参数属于sql语法的一部分,(表名,字段名)
6.3 多参数传递
方法1:mybatis底层只支持单参数传递,如果我们有多个参数要传递,需要把多参数封装起来(实体,map)。 方法2:有dao接口的情况下才可以使用,使用@Param注解 //mybatis底层会把多个参数封装称为map,默认key:un-uname:up-upwd param1-uname;param2-upwd Sysuser getByNameAndPwd(@Param("un") String uname, @Param("up") String upwd);
6.4 模糊查询
使用concat字符串拼接函数:建议使用这种 select * from sys_dept where dname like concat("%",#{dname},"%") 直接拼接: select * from sys_dept where dname like "%"#{dname}"%"
7.getMapper方法(最重要)
分两步来学习,今天学习使用;后天我们来看getMapper方法的源码.
1.定义dao接口; public interface SysuserDao { Sysuser getById(Integer id); List<Sysuser> listUsers(); Sysuser getByNameAndPwd(String uname,String upwd); Sysuser getByNameAndPwd2(Map map); int insert(Sysuser u); int update(Sysuser u); int delById(Integer id); } 2.定义映射文件: <mapper namespace="com.javasm.sys.dao.SysuserDao"> <insert id="insert"> insert into sys_user(uname, upwd) values(#{uname},#{upwd}) </insert> <update id="update"> update sys_user set upwd=#{upwd} where id=#{id} </update> <delete id="delById"> delete from sys_user where id=#{id} </delete> <select id="getById" resultType="com.javasm.sys.entity.Sysuser"> select * from sys_user where id=#{id} </select> <select id="listUsers" resultType="com.javasm.sys.entity.Sysuser"> select * from sys_user </select> <select id="getByNameAndPwd" resultType="com.javasm.sys.entity.Sysuser"> select * from sys_user where uname=#{a} and upwd=#{b} </select> <select id="getByNameAndPwd2" resultType="com.javasm.sys.entity.Sysuser"> select * from sys_user where uname=#{name} and upwd=#{pwd} </select> </mapper> <!--映射文件中namespace:必须是dao接口的全名--> <!--curd标签的id:必须是dao接口中的方法名--> 3.具体使用: @Test public void test1_getById() throws IOException { InputStream in= Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory f = new SqlSessionFactoryBuilder().build(in); SqlSession s = f.openSession(); SysuserDao ud = s.getMapper(SysuserDao.class);//得到接口类型的实例化对象 //当执行SysuserDao对象的getById方法时,底层得到对象的 包名.接口名 ,根据 包名.接口名 得到对应的MapedStatement;在根据接口方法的返回值判断是返回many或one,执行selectOne或selectList方法。 Sysuser byId = ud.getById(1); Map<String,String> map = new HashMap<String, String>(); map.put("name","fyt"); map.put("pwd","123456"); Sysuser byNameAndPwd2 = ud.getByNameAndPwd2(map); Sysuser u =new Sysuser(); u.setUname("aaa"); u.setUpwd("111"); int r = ud.insert(u); int i = ud.delById(4); s.commit(); s.close(); }
建议:搭建安装mybatisX插件,帮助我们做dao接口与映射文件之间的联动。
9.常见异常
异常产生原因:sqlSession.方法()第一个字符串参数写错了 IllegalArgumentException: Mapped Statements collection does not contain value for a.b.getById
映射文件路径错误 IOException: Could not find resource mapper/sys/sysUser-mapper1.xml
同一个映射文件中,curd标签的id重复。 IllegalArgumentException: Mapped Statements collection already contains value for a.b.getByUname. please check mapper/sys/sysuser-mapper.xml and mapper/sys/sysuser-mapper.xml
参数类型不一致 ClassCastException: java.lang.String cannot be cast to java.lang.Integer
ReflectionException: There is no getter for property named 'a' in 'class com.javasm.sys.entity.Sysdept'
总结:
orm框架的概念;
mybatis的核心对象:Configuration,sqlSessionFactory,SqlSession
curd操作:
多参数传递:
#{}与${}
getMapper方法的使用