目录
一.新增
二.修改
三.删除、根据Id查询
1.删除用户
2.根据Id查询
四.模糊查询
1.使用#定义参数
2.使用$定义参数
五.分页查询
1.顺序传参
2.@Param传参
3.POJO传参
4.Map传参
六.聚合查询
七.主键回填
一.新增
通过Navicat查看数据库,右键user表,点击设计表,可以看到表的各种设置
可以看到user表的id列是自增的,也就是插入数据时不需要设置id字段!
在接口文件里定义插入接口函数
然后在UserMapper.xml中设置接口函数的映射
不必在SqlMapConfig.xml中再配置了,因为之前已经配置过映射文件。
在User.java中再添加一个三个参数的构造函数,因为插入时不用插入id字段
public User(String username, String sex, String address) {
this.username = username;
this.sex = sex;
this.address = address;
}
编写测试方法 ,在 测试类里添加如下方法:
@Test
public void testAdd() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user=new User("塔姆","男","西安");
userMapper.add(user);
//提交事务,增删改都需要提交事务,否则数据库不会改变
session.commit();
//释放资源
session.close();
is.close();
}
注意:
- 当接口方法的参数类型为POJO类型时,SQL语句中绑定参数时使用 #{POJO的属性名} 即可。
- MyBatis事务默认手动提交,所以在执行完增删改方法后,需要手动调用SqlSession对象的事务提交方法,否则数据库将不发生改变。
运行测试方法,也要看到数据库里插入成功!
二.修改 优化测试类 我们发现 MyBatis 的测试方法在操作数据库前都需要获取代理对象,操作数据库后都需要释放资源,可以利用 Junit 的 前置后置方法 ,优化测试类代码。
这样Junit就会自动执行获取代理对象和释放资源的方法。 新建一个TestUserMapper2.java测试类,利用前置和后置将公共部分取出,降低代码冗余度。
package com.first.mapper;
import com.first.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestUserMapper2 {
//全局变量
InputStream is=null;
SqlSession session =null;
UserMapper userMapper =null;
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Before
public void before() throws IOException {
//(1)读取核心配置文件
is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
//(5)SqlSession对象获取代理对象
userMapper = session.getMapper(UserMapper.class);
}
后置方法:测试类里的测试方法执行之后都会执行后置方法
@After
public void after() throws IOException {
//(7)释放资源
session.close();
is.close();
}
}
在UserMapper.java中添加接口函数:
//修改数据 void update(User user);
在UserMapper.xml中注册映射:
编写测试函数:
package com.first.mapper;
import com.first.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestUserMapper2 {
//全局变量
InputStream is=null;
SqlSession session =null;
UserMapper userMapper =null;
//前置方法:测试类里的测试方法执行之前都会先执行前置方法
@Before
public void before() throws IOException {
//(1)读取核心配置文件
is= Resources.getResourceAsStream("SqlMapConfig.xml");
//(2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//(4)SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
//(5)SqlSession对象获取代理对象
userMapper = session.getMapper(UserMapper.class);
}
后置方法:测试类里的测试方法执行之后都会执行后置方法
@After
public void after() throws IOException {
//(7)释放资源
session.close();
is.close();
}
@Test
public void testUpdate(){
User user = new User(7,"吉米","女","深圳");
userMapper.update(user);
session.commit();
}
}
运行:
看到数据库已经更新
三.删除、根据Id查询
1.删除用户
在UserMapper.java中添加接口函数:
//删除用户 void delete(int userId);
在UserMapper.xml中配置映射:
注:当方法的参数类型是简单数据类型时, #{} 中可以写任意名称 ,就像形参那样,叫啥都行,比如我这里叫了sbID 简单数据类型:基本数据类型、字符串等 编写测试方法 :delete from user where id = #{sbID}
@Test
public void testDelete(){
userMapper.delete(7);
session.commit();
}
运行发现果然删除成功!
2.根据Id查询
在UserMapper.java中添加接口函数:
//根据id查找用户 User findById(int userId);
在UserMapper.xml中配置映射:
参数是用户的id,是int类型(故而参数名随便起了个userId),返回的结果是一个用户对象,类型是User
编写测试方法 :
@Test
public void testFindById(){
//查询操作没有修改数据库,不用提交事务
User user = userMapper.findById(1);
System.out.println(user);
}
输出:
User{id=1, username='小热', sex='男', address='北京'}
四.模糊查询
1.使用#定义参数
在UserMapper.java中添加接口函数(即持久层接口添加方法):
//根据用户名进行模糊查询 ListfindByUsernameLike(String username);
在UserMapper.xml中配置映射: (即映射文件添加标签 )
编写测试方法 :
@Test
public void testFindByUsernameLike(){
List users=userMapper.findByUsernameLike("%小%");
users.forEach(System.out::println);
}
运行:
名字里带小的都能查询出来
User{id=1, username='小热', sex='男', address='北京'}
User{id=2, username='小巴', sex='男', address='上海'}
User{id=3, username='小赵', sex='女', address='广州'}
User{id=4, username='小迪', sex='男', address='北京'}
User{id=5, username='小丽', sex='男', address='太原'}
我们看到在映射文件中,
parameterType
的值为
string
而没有写
java.lang.String
,这是为什么呢?
参数
/
返回值类型为基本数据类型
/
包装类
/String
等类型时,我们可以写全类名,也可以写别名。
2.使用$定义参数
模糊查询如果不想在调用方法时参数加
%
,可以使用拼接参数的方式设置
Sql
:
测试方法写法如下:
@Test
public void testFindByUsernameLike(){
List users=userMapper.findByUsernameLike("小");
users.forEach(System.out::println);
}
运行测试方法,发现运行成功,名字里带“小”的用户信息都被查出!
#和$ 的区别:- 1 #表示sql模板的占位符,$表示将字符串拼接到sql模板中。
- 2 #可以防止sql注入(相当于学JDBC时的PreparedStatement),一般能用#就不用$(相当于学JDBC时的Statement)。
- 3 ${}内部的参数名必须写value。
测试方法写法如下:
@Test
public void testFindByUsernameLike(){
List users=userMapper.findByUsernameLike("小");
users.forEach(System.out::println);
}
运行结果和上面一致!
五.分页查询
分页查询时, Sql 语句使用 limit 关键字,需要传入开始索引和每页条数两个参数。 MyBatis 的多参数处理有以下方式:1.顺序传参
Sql
中的参数使用
arg0
,
arg1...
或
param1
,
param2...
表示参数的顺序。
此方法可读性较低,在开发中不建议使用。
持久层接口方法 :
//下面的注释先把接口函数写完,然后在函数上一行打出
List findPage(int startIndex,int pageSize);
映射文件 :
测试类 :
@Test
public void testFindPage(){
List users = userMapper.findPage(0, 3);
users.forEach(System.out::println);
}
运行测试方法:
User{id=1, username='小热', sex='男', address='北京'}
User{id=2, username='小巴', sex='男', address='上海'}
User{id=3, username='小赵', sex='女', address='广州'}
2.@Param传参
在接口方法的参数列表中通过
@Param
定义参数名称,在
Sql
语句中通过注解中所定义的参数名称指定参数位置。
此方式参数比较直观的,推荐使用。
1
持久层接口方法 :
//推荐注解名和参数名一致,这样可读性高
List findPage1(@Param("startIndex") int startIndex, @Param("pageSize") int pageSize);
映射文件 :
测试类 :
@Test
public void testFindPage1(){
List users = userMapper.findPage1(3, 3);
users.forEach(System.out::println);
}
运行测试方法:
User{id=4, username='小迪', sex='男', address='北京'}
User{id=5, username='小丽', sex='男', address='太原'}
User{id=6, username='本本', sex='男', address='西安'}
3.POJO传参
自定义
POJO
类,该类的属性就是要传递的参数,在
SQL
语句中绑定参数时使用
POJO
的属性名作为参数名即可。
此方式推荐使用。
1
自定义
POJO :
在src/main/java/com/first/pojo/下创建PageQuery类
package com.first.pojo;
public class PageQuery {
private int startIndex;
private int pageSize;
public PageQuery() {
}
public PageQuery(int startIndex, int pageSize) {
this.startIndex = startIndex;
this.pageSize = pageSize;
}
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
持久层接口方法 :
//参数是一个类对象
List findPage2(PageQuery pageQuery);
映射文件:
测试函数:
@Test
public void testFindPage2(){
PageQuery pageQuery=new PageQuery(3,3);
List users = userMapper.findPage2(pageQuery);
users.forEach(System.out::println);
}
运行:
User{id=4, username='小迪', sex='男', address='北京'}
User{id=5, username='小丽', sex='男', address='太原'}
User{id=6, username='本本', sex='男', address='西安'}
4.Map传参
如果不想自定义
POJO
,可以使用
Map
作为传递参数的载体,在
SQL语句中绑定参数时使用
Map
的
Key
作为参数名即可。
此方法推荐使用。
1
持久层接口方法:
//参数是一个Map对象
List findPage3(Map params);
映射文件 :
测试函数:
@Test
public void testFindPage3(){
Map params = new HashMap();
params.put("startIndex",0);
params.put("pageSize",4);
List users = userMapper.findPage3(params);
users.forEach(System.out::println);
}
运行:
User{id=1, username='小热', sex='男', address='北京'}
User{id=2, username='小巴', sex='男', address='上海'}
User{id=3, username='小赵', sex='女', address='广州'}
User{id=4, username='小迪', sex='男', address='北京'}
在MyBatis中使用Map传参,Map键的类型为: String
六.聚合查询
举例:查询用户总数
持久层接口方法:int findCount();映射文件 : 测试方法:
@Test
public void testFindCount(){
System.out.println(userMapper.findCount());
}
运行输出:
7
七.主键回填
有时我们需要获取新插入数据的主键值。如果数据库中主键是自增的,这时我们就需要使用
MyBatis
的主键回填功能。
1
持久层接口方法:
void add2(User user);
映射文件:
SELECT LAST_INSERT_ID();
insert into user(username,sex,address)
values(#{username},#{sex},#{address})
SELECT LAST_INSERT_ID():查询刚刚插入的记录的主键值,只适用于自增主键,且必须和insert语句一起执行。
测试方法:
@Test
public void testAdd2(){
User user = new User("丽颖", "女", "南京");
//如果换成最开始写的add()函数,那么返回值是0
userMapper.add2(user);
session.commit();
System.out.println(user.getId());
}
运行:
9
到此为止的项目结构如下:



