目录
MyBatis返回类型
resultType
sql语句执行完后,数据封装的java对象
此对象类型是任意的,需要是该对象所属类的全限定名
<select id="selectUsers" resultType="org.example.domain.User">
select * from user order by `id`
</select>
简单参数
可以是一个简单参数如:int,String,Integer
<select id="selectUsers" resultType="int">
select count(*) from user
</select>
Map
只能返回一行数据
Map<String, Object> selectUserMapById(int id);
<select id="selectUserMapById" parameterType="java.lang.Integer" resultType="java.util.HashMap">
select id,name from user where id=#{id}
</select>
@Test
public void testSelectUserMapById(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
Map<String, Object> userMap = userDao.selectUserMapById(1);
System.out.println(userMap);
sqlSession.close();
}
resultMap
概述
结果映射,指定列名和java对象属性的对应关系。
MyBatis默认是找数据库的列名和其同名属性一 一对应,如果不希望这样,则可以使用resultMap
或你的数据库列名和实体类属性名不一样时,也需要使用resultMap
使用
1、先定义 resultMap标签
2、在select、update、insert等标签中使用
<resultMap id="selectUsersMap" type="org.example.domain.User">
<!--
主键列,使用id标签
column:列名
property:java实体类的属性名
-->
<id column="id" property="id"></id>
<!-- 非主键列,使用result-->
<!-- 这里将pwd、name调换了位置 -->
<result column="name" property="pwd"></result>
<result column="pwd" property="name"></result>
</resultMap>
<select id="selectUserById" resultMap="selectUsersMap">
select * from user where id=#{id}
</select>
3、再调用接口方法操作数据库
@Test
public void testSelectUserById(){
//使用动态代理的方式操作数据库
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.selectUserById(1);
System.out.println(user);
}
4、最后输出接口为
User{id=1, name='123', pwd='zs'}
可以看到,name、pwd调换了位置
5、除此之外
还可以用于,列名和实体类的所有属性名不同的情况,这个时候就不能用resultType了,需要使用resultMap。
除非,还可以在sql语句中使用 列别名AS
,来改列名和属性名对应,也可以。
因此,resultType和resultMap不要一起用
模糊查询
在java语句中传入like的内容
List<User> selectUserLikeFirstName(String firstName);
<select id="selectUserLikeFirstName" resultType="org.example.domain.User">
select * from user where name like #{firstName}
</select>
@Test
public void testSelectUserLikeFirstName(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> user = userDao.selectUserLikeFirstName("张%");
System.out.println(user);
sqlSession.close();
}
执行日志是这样的
==> Preparing: select * from user where name like ?
==> Parameters: 张%(String)
<== Columns: id, name, pwd
<== Row: 1, 张三, 123
<== Row: 9, 张飞, 123
<== Total: 2
[User{id=1, name='张三', pwd='123'}, User{id=9, name='张飞', pwd='123'}]
在mapper文件中拼接like的内容
<select id="selectUserLikeFirstName" resultType="org.example.domain.User">
select * from user where name like #{firstName} "%"
</select>
只需在mapper中如上用空格分隔开,用双引号包裹字符即可
@Test
public void testSelectUserLikeFirstName(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> user = userDao.selectUserLikeFirstName("张");
System.out.println(user);
sqlSession.close();
}
动态SQL
概述
sql语句的内容是变化的,可以根据条件获取到不同的sql语句:主要是where的变化
动态sql的实现,使用的是Mybatis提供的标签:<if>
, <where>
, <foreach>
if
<select id="selectUserIf" resultType="org.example.domain.User">
select * from user
<!--
如果满足test=“”中的条件,则会执行
select * from user where name=#{name}
sql语句,否则就只有where之前的语句
-->
<if test="name != null and name != '' ">
where name=#{name}
</if>
</select>
但是这种情况,如果where在<if>
外面,而传入的参数又不满足条件,则会出现语法错误的情况,此时可以在where后面加上1=1
或者id > 0
然后<if>
中用and
连接,则可保证语法正确。
当然,Mybatis肯定想到了这种问题,也就是<where>
where
用来包含多个<if>
标签,当多个<if>
有一个成立的,<where>
会自动增加一个where关键字,并去掉多余的and、or等关键字。
<select id="selectUserWhere" resultType="org.example.domain.User">
select * from user
<where>
<if test="name != null and name != ''">
name=#{name}
</if>
</where>
</select>
@Test
public void testSelectUserWhere(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = new User();//这里没有给user的属性赋值
List<User> users = userDao.selectUserWhere(user);
for (User user1 : users) {
System.out.println(user1);
}
sqlSession.close();
}
以上代码没有给user的属性赋值,而mapper文件中也没有使用where关键字,而使用<where>
标签代替,最终查出的只有<where>
标签之外的sql语句。
==> Preparing: select * from user
==> Parameters:
<== Columns: id, name, pwd
<== Row: 1, 张三, 123
<== Row: 2, 李四, 123
<== Row: 3, 王五, 123
<== Row: 4, 赵云, 123
<== Row: 5, 赵六, 123
<== Row: 6, 刘备, 123
<== Row: 7, 宋江, 123
<== Row: 8, 孙八, 123
<== Row: 9, 张飞, 123
<== Total: 9
User{id=1, name='张三', pwd='123'}
User{id=2, name='李四', pwd='123'}
User{id=3, name='王五', pwd='123'}
User{id=4, name='赵云', pwd='123'}
User{id=5, name='赵六', pwd='123'}
User{id=6, name='刘备', pwd='123'}
User{id=7, name='宋江', pwd='123'}
User{id=8, name='孙八', pwd='123'}
User{id=9, name='张飞', pwd='123'}
而如果,<if>
满足条件的情况下:
如,在创建user对象下方,加入user.setName("张飞");
查出的结果则为
==> Preparing: select * from user WHERE name=?
==> Parameters: 张飞(String)
<== Columns: id, name, pwd
<== Row: 9, 张飞, 123
<== Total: 1
User{id=9, name='张飞', pwd='123'}
我们再测试一下Mybatis会不会将多余的or、and关键词删除:
<select id="selectUserWhere" resultType="org.example.domain.User">
select * from user
<where>
<if test="name != null and name != ''"><!-- 名字不为空的时候执行此字段 -->
name=#{name}
</if>
<if test="id > 5"><!-- 查询的id大于时执行此字段 -->
or id>#{id}
</if>
</where>
</select>
这里是,查询姓名=刘备 或者 id>6 的用户
==> Parameters: 刘备(String), 6(Integer)
<== Columns: id, name, pwd
<== Row: 6, 刘备, 123
<== Row: 7, 宋江, 123
<== Row: 8, 孙八, 123
<== Row: 9, 张飞, 123
<== Total: 4
User{id=6, name='刘备', pwd='123'}
User{id=7, name='宋江', pwd='123'}
User{id=8, name='孙八', pwd='123'}
User{id=9, name='张飞', pwd='123'}
这里是没有给姓名赋值:
user.setId(6);
可以看到下方的sql中,并没有or
关键词
==> Preparing: select * from user WHERE id>?
==> Parameters: 6(Integer)
<== Columns: id, name, pwd
<== Row: 7, 宋江, 123
<== Row: 8, 孙八, 123
<== Row: 9, 张飞, 123
<== Total: 3
User{id=7, name='宋江', pwd='123'}
User{id=8, name='孙八', pwd='123'}
User{id=9, name='张飞', pwd='123'}
for each
循环java中的数组、List集合的。主要用于sql语句中的in
关键词
如:select * from user where id in (1,2,3)
查询 id 为1,2,3的用户
后面括号中的1、2、3就需要在java中使用数组或List集合封装好,然后由foreach
标签循环
<foreach collection="表示接口中的方法参数的类型,数组就是array,List就是list"
item="表示循环的每个元素,自定义的,就是java增强for循环中用来表示当前循环的元素的变量"
open="表示开始的元素,如上面需要用括号括起来,则开始元素为'(' "
close="表示结束的元素"
separator="表示中间每个元素的分隔符,如上面的就需要用逗号','分隔 ">
</foreach>
循环简单参数
这是第一种用法,循环List中存放 数字、字符串
<select id="selectUserForeachOne" resultType="org.example.domain.User">
select * from user where id in
<foreach collection="list" item="id" open="(" separator="," close=")" >
#{id} <!-- 与上面的item对应 -->
</foreach>
</select>
@Test
public void testSelectUserForeachOne(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
List<User> users = userDao.selectUserForeachOne(list);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
从日志来看,这里Mybatis帮我们循环生成了一个带有占位符的字符串( ? , ? , ? )
而后也用list中的元素填充了:Parameters: 1(Integer), 2(Integer), 3(Integer)
==> Preparing: select * from user where id in ( ? , ? , ? )
==> Parameters: 1(Integer), 2(Integer), 3(Integer)
<== Columns: id, name, pwd
<== Row: 1, 张三, 123
<== Row: 2, 李四, 123
<== Row: 3, 王五, 123
<== Total: 3
User{id=1, name='张三', pwd='123'}
User{id=2, name='李四', pwd='123'}
User{id=3, name='王五', pwd='123'}
循环实体类属性
一般情况下,我们都是将参数封装进实体类再存放进集合或数组的,而Mybatis也提供了这种用法
<select id="selectUserForeachTwo" resultType="org.example.domain.User">
select * from user where id in
<foreach collection="list" item="user" open="(" separator="," close=")" >
#{user.id} <!-- 直接用item.属性名即可 -->
</foreach>
</select>
List<User> selectUserForeachTwo(List<User> users);
@Test
public void testSelectUserForeachTwo(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> list = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
User user = new User();
user.setId(i);
list.add(user);
}
List<User> users = userDao.selectUserForeachTwo(list);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
执行结果为:
==> Preparing: select * from user where id in ( ? , ? , ? )
==> Parameters: 1(Integer), 2(Integer), 3(Integer)
<== Columns: id, name, pwd
<== Row: 1, 张三, 123
<== Row: 2, 李四, 123
<== Row: 3, 王五, 123
<== Total: 3
User{id=1, name='张三', pwd='123'}
User{id=2, name='李四', pwd='123'}
User{id=3, name='王五', pwd='123'}
sql代码片段
<sql id="userSQL">
在这里定义sql语句
</sql>
<select id="select">
使用include标签进行复用
<include refid="userSQL"></include>
</select>
总结
综上所述:其实,动态sql的本质就是Mybatis帮你拼sql语句的字符串,因此sqlmapper的语句是很灵活的,( )可以自己在foreach外自定义也没问题。
使用数据库配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false
username=root
password=root
<properties resource="db.properties"></properties>
<dataSource type="POOLED">
<!--
配置数据库的各种信息
${driver}中的字段与properties中的key相对应
-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
数据分页
1、maven引入依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
2、mybatis引入插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3、使用
@Test
public void testSelectAllUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
//分页
//pageNum:第几页
//pageSize:每页几行
PageHelper.startPage(2,3);//第二页,三行数据
List<User> users = userDao.selectAllUser();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
最终的输出结果为:
==> Preparing: SELECT count(0) FROM user //这里查询了共有多少行数据,从而判断能分多少页
==> Parameters:
<== Columns: count(0)
<== Row: 9
<== Total: 1
==> Preparing: select * from user LIMIT ?, ?
==> Parameters: 3(Integer), 3(Integer)//这里自动帮我们填充好了limit,从第3行数据开始,分三行数据,也就是每页三行显示第二页
<== Columns: id, name, pwd
<== Row: 4, 赵云, 123
<== Row: 5, 赵六, 123
<== Row: 6, 刘备, 123
<== Total: 3
User{id=4, name='赵云', pwd='123'}
User{id=5, name='赵六', pwd='123'}
User{id=6, name='刘备', pwd='123'}