文章目录
🕊前言
MyBatis 的真正强大在于它的语句
映射
,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
下面介绍的都是元素比较常用的属性,如若想要了解更多属性,欢迎点击Mybatis3中文官方文档
以下所有的解析使用的数据库表为user表,以下为数据:
🕊查询元素select
常用的属性
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常! |
---|---|
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
resultType | 期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。 |
resultMap | 对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。 |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。 |
案例
1、查询所有用户
UserMapper接口
// 查询所有用户
List<User> getUserList();
UserMapper.xml
<select id="getUserList" resultType="com.xmonster.pojo.User">
select * from mybatis.user
</select>
注意返回值的类型写法
2、根据id查询某用户
UserMapper接口
// 根据id查询某用户
User getUserId(int id);
UserMapper.xml
<select id="getUserId" parameterType="int" resultType="com.xmonster.pojo.User">
select * from mybatis.user where id=#{id}
</select>
3、模糊查询
注意:Java代码执行的时候,传递通配符%
UserMapper接口
// 模糊查询
List<User> getUserLike(String value);
UserMapper.xml
<select id="getUserLike" resultType="com.xmonster.pojo.User">
select * from mybatis.user where name like "%"#{value}"%";
</select>
🕊insert, update 和 delete
参数
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 在命名空间中唯一的标识符,可以被用来引用这条语句。 id的值一般和DAO接口的方法名一致,如果不唯一或者不一致,MyBatis将抛出异常! |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset )。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
案例
UserMapper.java
// 插入用户
int addUser(User user);
// 万能的map插入
int addUser2(Map<String, Object> map);
// 更新用户
int updateUser(User user);
// 万能map修改用户密码
int updateUser2(Map<String, Object> map);
// 删除用户
int deleteUser(int id);
UserMapper.xml
<insert id="addUser" parameterType="com.xmonster.pojo.User" >
insert into mybatis.user (id,name ,pwd) values (#{id}, #{name}, #{pwd})
</insert>
<!-- 万能map,values后面的#{},括号里的值可以不用和User对象的属性名一一对应,反正传递的时map的key值-->
<insert id="addUser2" parameterType="map" >
insert into mybatis.user (id,name ,pwd) values (#{userId}, #{userName}, #{Password})
</insert>
<update id="updateUser" parameterType="com.xmonster.pojo.User">
update mybatis.user set name=#{name}, pwd=#{pwd} where id=#{id}
</update>
<!-- 万能map修改用户密码-->
<update id="updateUser2" parameterType="map">
update mybatis.user set pwd=#{Password} where id=#{userId}
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
test.java
//add
@Test
public void test1(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
int blue = mapper.addUser(new User(4, "blue", "19334"));
sqlSession.commit();
sqlSession.close();
}
//map 插入
@Test
public void test2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<>();
map.put("userId", 4);
map.put("userName", "aa");
map.put("Password", "444444");
mapper.addUser2(map);
sqlSession.commit();
sqlSession.close();
}
//更新
@Test
public void test3(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.updateUser(new User(4,"red","222222"));
sqlSession.commit();
sqlSession.close();
}
//map指定元素更新
@Test
public void test4(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<>();
map.put("userId", 4);
map.put("Password", "333333");
mapper.updateUser2(map);
sqlSession.commit();
sqlSession.close();
}
//删除用户
@Test
public void test5(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.deleteUser(4);
sqlSession.commit();
sqlSession.close();
}
注意点
每次使用增删改查之后,不要忘记提交事务:sqlSession.commit();
也可以选择在(一般放在工具类里)MybatisUtils里,也就是生成sqlsession的函数中,在执行返回值的时候,参数选择true,这样每次你执行的时候都会自动提交事务:
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
🕊sql元素
对重复的sql语句进行组装起来,使用SQL标签抽取
公共部分,在需要使用的地方include即可。下面是个例子,没有任何前后逻辑,就是单纯的例子:
Mapper.xml:
<sql id="if-title-author">
<if test="title != null">
and title=#{title}
</if>
<if test="author != null">
and author=#{author}
</if>
</sql>
<!-- 查询博客-->
<select id="queryBolg" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<include refid="if-title-author"></include>
</where>
</select>
用标签引入,refid
填sql片段的id即可
抽取的原则
- 最好基于单表来定义SQL片段!
- 不要存在where标签,把where丢进去就没啥用了,去想想什么才叫
复用
🕊参数
MyBatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javaType,除非该对象是一个 HashMap
,这个时候,你需要显式指定 javaType 来确保正确的类型处理器(TypeHandler)被使用。
情景一:省略parameterType(无注解情况)
传入的参数是简单的int类型,就比如上面的根据id查询用户信息,其实我也可以不用写parameterType,系统会自动的进行匹配,甚至在Mapper.xml里#{}括号里的参数也可以和接口参数名字不一致,
下面是针对输入一个参数的测试
Mapper.xml:
<select id="getUserId" resultType="com.xmonster.pojo.User">
select * from mybatis.user where id=#{uid}
</select>
上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parameterType)会被自动设置为 int,这个参数可以随意命名
。
但是这里只是针对这种非常简单的情况,这里的简单是指首先查询语句简单,其次就是传递的参数很简单,但是原始类型
或简单数据类型
(比如 Integer 和 String)因为没有其它属性,会用它们的值来作为参数。
再来一次测试
需求:输入用户的名字,输出对应用户的所有信息
UserMapper接口
// 根据输入用户的名字输出对应用户信息
User getUserName(String name);
UserMapper.xml
<select id="getUserName" resultType="com.xmonster.pojo.User">
select * from mybatis.user where name=#{uname}
</select>
但是为了规范,#{}括号里的参数最好和接口参数名称一致,就不要向上面一样又是id,又是uid
输入两个参数
这里就有要注意的点了,先来看一下代码
UserMapper接口
// 根据输入的用户姓名和密码查找对应的用户信息
User getUserByNamePwd(String name, String pwd);
UserMapper.xml
<select id="getUserByNamePwd" resultType="com.xmonster.pojo.User">
select * from mybatis.user where name=#{name} and pwd=#{pwd};
</select>
test.java
@Test
public void test9(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
User userId = mapper.getUserByNamePwd("xmonster","123456");
System.out.println(userId);
sqlSession.close();
}
结果发现报错:
顺序映射方式(不使用注解和map)
原因:在Mybatis中当映射器需要多个参数的时候,有三种方法,一种是需要是需要导包的,这里与其说是要导包不如说是要用注解来解决问题;还有map;还有一种就是使用它默认的参数,这也就是顺序映射方式
我们只需要改变XML配置当中的参数即可,但是我们一般如果说是多参数,又不想用注解,又不想用map,就是想要单纯的
两个参数来达到目的的话,一般这几个参数的参数类型都是同一个类型
就如果说你想通过id和name去查用户信息,id和name一个是int,一个是String,那么你的parameterType就不好写,简单来说也没人会这么用,除非这几个参数是同一个类型,或者你传入的参数是一个对象,不过在输入的时候你就要三个属性都输入,显然这和我只想要输入两个参数的目的不符
举个例子,想要通过输入用户名字和密码查询该用户所有信息,就只输入两个参数,不输入id的情况
UserMapper接口
// 输入用户id和名字,输出对应的用户的信息
User getUserNamePwd(String name, String Pwd);
UserMapper.xml
<select id="getUserNamePwd" parameterType="String" resultType="com.xmonster.pojo.User">
select * from mybatis.user where name =#{param1} and pwd=#{param2}
</select>
test.java
@Test
public void test9(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);//得到接口
User user = mapper.getUserNamePwd("xmonster", "123456");
System.out.println(user);
sqlSession.close();
}
测试发现通过:
小结
顺序映射方法其实使用的情况比较少,可以看到在Mapper.xml中参数用的是param1 param2这也和上面的报错信息一致,旧版本的Mybatis用的是#{0} #{1}进行映射的
情景二:使用注解
先解决一下上面的问题
直接修改
UserMapper接口
// 根据输入的用户姓名和密码查找对应的用户信息
User getUserByNamePwd(@Param("id") int id, @Param("name") String name, @Param("pwd") String pwd);
其他不变,可以看到,我们成功查出
当然了使用注解就可以不用管多少个参数了,参数类型一不一致了,在传参的时候Mapper.xml文件中#{}括号里写入的参数是@Param里的,而不是你自己定义的参数名字
比如
// 根据输入的用户姓名和密码查找对应的用户信息
User getUserByNamePwd(@Param("uid") int id, @Param("uname") String name, @Param("upwd") String pwd);
那么在Mapper.xml中就只认得uid/uname/upwd
,传参时注意
小结
关于@param()注解
- 基本类型的参数或者String类型,需要加上
- 引用类型不用加
- 如果只有一个基本类型,可以忽略,但是建议大家都加上!
- 我们在SQL中引用的就是我们这里的@Param()中设定的属性名!
使用map
使用ma直接看上方案例即可。