JDBC的缺点
硬编码
在注册驱动和获取连接的时候,url,name等用字符串存储,存在硬编码
查询所用的sql语句也是用String存储,存在硬编码
虽然可以通过封装JDBC工具类的方式,读取Properties文件来解决硬编码的问题,但还是较为繁琐。
操作繁琐
需要手动设置参数
需要手动封装结果集
Mybatis简化方式
在使用JDBC时,我们首先需要创建Dao层的接口,并写出相应的实现类。
而使用Mybatis后,我们只需要给出Dao层的接口(一般被称作Mapper),然后再对应的MapperXml文件中配置好sql语句。Mysql就会自动给我们生成好一个实现类。完成获取结果封装结果集等一系列操作
快速入门
结构
配置mybatis-config.xml
这是mybatis的核心配置文件
1 |
|
dataSource标签里的内容为连接数据库的链接和用户名密码等。
mappers标签内配置所有mapper配置文件的位置,Mybatis会按照这里面的内容来逐个生成实现类。
获取SqlSession
要拿到Mybatis给我们生成的这个实现类对象,我们需要一个SqlSession对象。这一对象的构造采用了工厂的设计模式,因此我们要先拿到一个SqlSessionFactory对象。
1 | String resource = "org/mybatis/example/mybatis-config.xml"; |
然后再通过下面的方法,即可拿到Sqlsession对象
1 | SqlSession session = sqlSessionFactory.openSession() |
通常我们会将上面的代码封装成一个工具类,如下
1 | public class MybatisUtils { |
这样便可以通过getSqlSession()方法便捷的获取到一个SqlSession对象
创建pojo类
创建pojo类,并提供get和set方法。以便mybatis帮我们自动的把数据封装到对象里
对于pojo类中的变量名,可以与sql查询结果的列名相同,也可以不同。若不同后续则需要配置ResultMap
配置mapper
对于mapper的配置主要分为三个部分
定义mapper接口
1 | public interface UserMapper { |
定义方法名和对应的返回值
配置对应的xml
我们在对应的位置建立一个UserMapper.xml,使得xml和接口在同一目录下
1 |
|
注意,此处这种配置的方式,就是让Mybatis自动的帮我们把sql查询到的数据给封装到我们指定的pojo对象中。
Mybatis会将sql语句返回结果的列名和pojo对象的变量名一一对应,若二者名字相同则可以自动对应。
若不同,我们当然可以通过类似下面的方式修改sql语句来更改查询结果的别名以完成匹配,但每次都要修改过于繁琐。
1 | select name as user_name from user; |
Mybatis提供了一种ResultMap,可以帮我们很好的解决这一问题,配置示例如下
1 | <mapper namespace="com.shijivk.mapper.UserMapper"> |
在mapper标签中填写resultMap标签。其中id为唯一标识,type指定为要映射的pojo类
column为查询结果的列名,property为pojo类中的变量名
在下面的select标签中,指定resultMap属性来替代resultType属性,值指定为上面定义的map的id即可。
在mybatis-config.xml中配置mapper
1 | <mappers> |
使用
1 | SqlSession sqlSession = MybatisUtils.getSqlSession(); |
首先我们通过工具类拿到SqlSession
再通过sqlSession.getMapper()方法拿到mapper
最后直接调用mapper的方法即可。
条件查询
参数只有一个基本类型时
mapper配置
1 | User selectById(int uid); |
xml配置
1 | <select id="selectById" resultType="com.shijivk.pojo.User"> |
此时直接采用#{}作为占位符(后面再讨论占位符的种类)
此时Mybatis会直接把形参中唯一一个变量赋值到占位符的位置。
注意:此处并不是按照下图中两个位置的名字来进行匹配的。能匹配上仅仅是因为此时只有一个形参和一个占位符。
例如我们增加一个形参,并保持xml文件中的名字不变
1 | User selectById(int uid,int num); |
会发现此时并没有匹配上,而是报错。从报错内容中我们可以看出,Mybatis在用户没有指定形参的名字的时候,默认采用的是arg1,arg0之类的名字。我们把占位符处的值改为arg0,发现便可以正常匹配了。
1 | select * from user where id = #{arg0}; |
但此种方式太难使用,因此我们采用注解的方式来给形参命名。
采用注解来命名形参
在mapper的形参处加上下面所示的注解
1 | User selectById(int id, int num); |
此时便可以在#{}中用uid和num两个名称来传递这两个形参了
1 | <select id="selectById" resultType="com.shijivk.pojo.User"> |
采用对象或Map的方式封装参数
1 | User selectById(User user); |
1 | <select id="selectById" resultType="com.shijivk.pojo.User"> |
我们可以直接传入一个对象参数,然后在占位符里面直接写对象内部的变量名,Mybatis就会自动的从传入的对象中取出相应的值。
当然上述传入的参数可以替换为Map,也是同样的直接使用其内部的变量名称取值即可。
占位符的区别
${}类似于jdbc中的statement,是直接使用拼串的操作来进行的。不能防sql注入。一般只有在查询的表的名称或者是列的名称不确定时使用,用它放在列名的位置上用于占位
#{}类似于jdbc中的PreparedStatement,先用?作为占位符,然后再set参数,安全性略高。
动态查询
对于一些多条件筛选的情况。例如我们的页面上有公司的位置和公司的类型两个选项,用户可以通过选择这两个选项中的一个或是全都选择,来从数据库中查询一些公司。那么如果我们的sql语句是静态的,我们就需要对两个选项是否选择,共计三种情况,分别写出对应的sql语句,这样的操作过于繁琐。
Mybatis提供了一些标签。可以帮助我们实现动态sql
if标签
1 | <select id="selectUser" resultType="com.shijivk.pojo.User"> |
在if标签中的test属性里的判别式成立时,标签中的内容才会被加到sql语句中
但此时存在着一个问题,如果没有id,那么where关键词会和and关键词直接相连。
这种情况下有两个解决方式,一个是在where的后面加上 1 = 1 之类的恒等式,然后在id前面加and,但不够美观。
第二种方式便是采用Mybatis提供的where标签
where标签
where标签会自动检测里面的逻辑连接符是否多余,如果多余会自动将其去掉,同时如果所有条件均没有,那么where关键字也会被去掉。
1 | <select id="selectUser" resultType="com.shijivk.pojo.User"> |
如果条件是n选1的话,还可以采用choose等标签来解决。
Mybatis事务
Mybatis默认关闭了自动提交。因此如果进行增删改操作,完成后需要用下面的方法来提交事务
1 | sqlSession.commit(); |
除此之外我们也可以在创建session的时候开启自动提交
1 | sqlSessionFactory.openSession(true); |
向openSession方法中传入参数true,可以开启自动提交
增加&修改
增加
1 | void add(User user); |
1 | <insert id="add"> |
添加方法返回值为void即可,出现错误直接抛出异常。
完成后commit事务即可。
主键返回
在添加完对象后,想获取其在数据库中的主键值,就需要使用主键返回。
例如上面的案例,在数据库中,id这一项被设置为了auto_increament,因此我们在insert的时候不需要输入id,但我们在添加完后可能有其他的操作需要用到id,这个时候,我们需要在insert标签上添加两个属性
1 | <insert useGeneratedkKeys = "true" keyProperty = "id"> |
这样便可以开启主键返回,在调用完add方法后,mybatis会自动将数据库中返回的id值,赋值给传入add方法的那个user对象,我们只需要用getter拿到值即可。
修改
修改和增加的操作基本一致,只是将insert标签换成update标签,然后在其中写update的sql语句即可
返回值也是void
如果要修改动态字段,那么需要借助if标签和set标签(和where标签类似)等。
删除
将标签换位delete即可,返回值为void
要实现批量删除的话需要传入一个数组,然后通过foreach标签遍历即可
注解开发
对于一些比较简单的sql语句,我们可以直接通过注解的方式开发
1 |
|
Mybatis提供了@Select,@Insert,@Update,@Delete四种注解,只需要按照和xml中相同的方式在Mapper的方法定义上方写上sql语句即可。