1. 深入Mybatis映射配置文件
1.1. CRUD语句定义
查询语句
UserMapper.java接口中
public List<User> queryAllUser();
public User queryUserById(Integer id);
UserMapper.xml配置文件中
<select id="queryAllUser" resultType="uSer">
select * from user;
</select>
<!--根据id查询用户信息-->
<!--#{} : 如果传递的参数是基本数据类型,其中的内容可以随便写
如果传递的参数是实体类对象类型,其中的内容必须是实体类属性名
parameterType:Mybatis允许不写,会自动进行类型转换,
如果参数需要数值类型,传递的是字符串:
1.如果字符串是纯数字,直接转换
2.如果字符串是数字+字符形式,会将数字之后的字符提
出,只留数字转换
3.如果字符串是字符+数字形式,无法转换
-->
<select id="queryUserById" parameterType="int" resultType="user">
select * from user where id=#{传递的参数是id}
</select>
MybatisTest.java单元测试类
@Test
public void test1(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.queryAllUser();
System.out.println(users);
}
@Test
public void test2(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
System.out.println(user);
}
插入语句
普通插入语句
UserMapper.java接口中
public void insertUser(User user);
UserMapper.xml配置文件中
<insert id="insertUser" parameterType="user">
insert into user(id,user_name,password) values(#{id},#{userName},#{password})
</insert>
MybatisTest.java单元测试类
@Test
public void test3(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(7,"张飞","23423");
mapper.insertUser(user);
//sqlSession.commit();
}
细节
mybatis默认会开启事务执行操作,但是默认是不会自动提交事务,所以插入操作执行之后,需要手动提交事务,或者配置sqlSession自动提交事务。
如何返回数据库自增的ID
如何返回数据库自增的ID Mybatis默认插入数据之后,是不会返回新插入数据的id的。
UserMapper.java接口中
public void insertUserGetId(User user);
UserMapper.xml配置文件中
<insert id="insertUserGetId" parameterType="user">
insert into user(user_name,password) values(#{userName},#{password})
</insert>
MybatisTest.java单元测试类
@Test
public void test4(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUserName("关平");
user.setPassword("234234");
mapper.insertUserGetId(user);
System.out.println(user.getId());
}
运行测试,会发现并不能在插入操作之后,获取新插入数据的id.
如果想要在插入数据之后立刻返回新插入数据的id,需要进行以下操作。
方式一:
<!--添加用户,获取新增用户的自增id方式一
useGeneratedKeys : true表示可以获取新增数据主键
keyColumn : 数据库表中主键字段的名称
keyProperty : 参数条件实体类对象的属性名,表示存放数据库主键字段数据的属性
-->
<insert id="insertUserGetId" parameterType="user" useGeneratedKeys="true"
keyColumn="id" keyProperty="id">
insert into user(user_name,password) values(#{userName},#{password})
</insert>
方式二:
<!--添加用户,获取新增用户的自增id方式二
selectKey : 存放获取新增数据主键数据的sql语句
order: 在新增之前还是之后执行sql语句 BEFORE:之前 AFTER:之后
keyColumn : 数据库表中主键字段的名称
keyProperty : 参数条件实体类对象的属性名,表示存放数据库主键字段数据的属性
resultType : 查询的主键字段的类型
-->
<insert id="insertUserGetId" parameterType="user">
<selectKey keyColumn="id" keyProperty="id" resultType="integer" order="AFTER">
select LAST_INSERT_ID();
</selectKey>
insert into user(user_name,password) values(#{userName},#{password})
</insert>
会发现可以获取到新插入的数据的id。
删除语句
UserMapper.java接口中
public void deleteUserById(Integer id);
UserMapper.xml配置文件中
<delete id="deleteUserById" parameterType="integer">
delete from user where id=#{id}
</delete>
MybatisTest.java单元测试类
@Test
public void test5(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUserById(16);
}
更新语句
UserMapper.java接口中
public void updateUser(User user);
UserMapper.xml配置文件中
<update id="updateUser" parameterType="user">
update user set password=#{password} where id=#{id}
</update>
MybatisTest.java单元测试类
@Test
public void test6(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(15);
user.setPassword("spring");
mapper.updateUser(user);
}
1.2. 接口中的参数如何传递到SQL中
简单类型参数
UserMapper.java接口中:
public void deleteUserById(Integer id);
UserMapper.xml配置文件中:
<delete id="deleteUserById" parameterType="integer">
delete from user where id=#{id}
</delete>
引用类型参数
UserMapper.java接口中:
public void insertUser(User user);
UserMapper.xml配置文件中:
<insert id="insertUserGetId" parameterType="user" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into user(user_name,password) values(#{userName},#{password})
</insert>
多参数传递
方式一
如果传递的参数有多个,Mybatis默认会按照传递参数的顺序命名为arg0、arg1......,在映射文 件中可以直接使用arg0、arg1......获取传递的参数。
UserMapper.java接口中
public User queryUserByIdAndUserName(int id,String userName);
UserMapper.xml配置文件中
<!--多参数传递方式一
arg0和arg1固定写法
arg0表示mapper接口方法第一个参数
arg1表示mapper接口方法第二个参数
-->
<select id="queryUserByIdAndUserName" resultType="user">
select * from user where id=#{arg0} and user_name=#{arg1}
</select>
方式二
如果传递的参数有多个,Mybatis默认会按照传递参数的顺序命名为param1、param2......,在 映射文件中可以直接使用param1、param2......获取传递的参数。
UserMapper.java接口中
public User queryUserByIdAndUserName(int id,String userName);
UserMapper.xml配置文件中
<!--多参数传递方式二
param1和param2固定写法
param1表示mapper接口方法第一个参数
param2表示mapper接口方法第二个参数
-->
<select id="queryUserByIdAndUserName" resultType="user">
select * from user where id=#{param1} and user_name=#{param2}
</select>
方式三
如果传递的参数有多个或接口方法中的参数名称和映射文件中使用的参数名称不一致,可以使用 @param()指定接口方法参数在映射文件中使用的名称。
UserMapper.java接口中
//@Param : 给mapper接口方法的参数设置一个在mapper.xml文件中使用的名称
public User queryUserByIdAndUserName(@Param("id") int id,
@Param("userName") String userName);
UserMapper.xml配置文件中
<!--多参数传递方式三-->
<select id="queryUserByIdAndUserName" resultType="user">
select * from user where id=#{id} and user_name=#{userName}
</select>
MybatisTest.java单元测试类
@Test
public void queryUserByUserNameAndPassWordTest() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("Mybatis-Config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//采用动态代理的方式,构建出usermapper实现类对象
User user = mapper.queryUserByIdAndUserName(10, "赵云");
System.out.println(user);
sqlSession.close();
}
#{}与${}的区别
共同点:
它俩都可以获取接口调用中传递过来的参数。
区别:
#{} (建议使用)
1.表示占位符 ?
2.如果参数只有一个基本类型,#{名称}中的名称可以随便写
3.如果参数是实体类对象类型,#{名称}必须实体类中的属性名一致
4.可以防止sql语句注入
${}
1.直接拼接sql, '${username}'
2.如果参数只有一个基本类型参数低版本必须使用${value},但是高版本可以随便写
3.如果参数是实体类对象类型,${名称}必须实体类中的属性名一致
4.不可以防止sql注入,比如:内容为' or '1'='1
比如,要实现下面的效果:
UserMapper.java接口中
public User selectUserById(int id); //ctrl+d复制一行 ctrl+y删除一行
public User selectUserByUserName(String userName); //ctrl+d复制一行ctrl+y删除一行
public List<User> selectUserByStrId(String id);
UserMapper.xml配置文件中
<!--${}用法-->
<select id="selectUserById" parameterType="_int" resultType="user">
select * from user where id=${随便写}
</select>
<select id="selectUserByUserName" parameterType="string" resultType="user">
select * from user where user_name='${随便写}'
</select>
<select id="selectUserByStrId" parameterType="string" resultType="user">
select * from user where id='${id}'
</select>
MybatisTest.java
@Test
public void selectUserByIdTest() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("Mybatis-Config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//采用动态代理的方式,构建出usermapper实现类对象
User user = mapper.selectUserById(10);
System.out.println(user);
sqlSession.close();
}
@Test
public void selectUserByUserNameTest() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("Mybatis-Config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//采用动态代理的方式,构建出usermapper实现类对象
User user = mapper.selectUserByUserName("赵云");
System.out.println(user);
sqlSession.close();
}
@Test
public void selectUserByStrIdTest() throws IOException {
InputStream resourceAsStream =Resources.getResourceAsStream("Mybatis-Config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//采用动态代理的方式,构建出usermapper实现类对象
List<User> user = mapper.selectUserByStrId("' or '1'='1");
System.out.println(user);
sqlSession.close();
}
细节:
如果使用#{id}取获取参数,最终执行的SQL会是这样:
如果使用${id}来取参数,最终执行的SQL会是这样:
1.3. 结果集如何映射
ResultType方式
ResultType方式适用于数据库结果集可以直接映射成一个Java类的情况
Java实体类:
public class User {
private int id;
private String userName; //可以通过Mybatis的配置实现 user_name和userName的对应
private String password;
public User() {
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public User(int id, String userName, String password) {
this.id = id;
this.userName = userName;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
使用方法:
<select id="queryAllUser" resultType="uSer">
select * from user;
</select>
ResultMap方式
ResultMap方式适用于复杂的结果集映射,比如数据库返回的结果集中的列名和JavaBean无法一 一对应,或者对象间存在一对一、一对多关联映射时。
解决数据库列名与Java类中属性名不一致的映射问题
User_ResultMap.java实体类
public class User_ResultMap {
private Integer id;
private String un;
private String pw;
public User_ResultMap() {
}
public User_ResultMap(String un, String pw) {
this.un = un;
this.pw = pw;
}
public User_ResultMap(Integer id, String un, String pw) {
this.id = id;
this.un = un;
this.pw = pw;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUn() {
return un;
}
public void setUn(String un) {
this.un = un;
}
public String getPw() {
return pw;
}
public void setPw(String pw) {
this.pw = pw;
}
@Override
public String toString() {
return "User_ResultMap{" +
"id=" + id +
", un='" + un + '\'' +
", pw='" + pw + '\'' +
'}';
}
}
UserResultMapMapper.java接口
public interface UserResultMapMapper {
public List<User_ResultMap> queryAllUser();
}
UserResultMapMapper.xml配置文件
<mapper namespace="com.test.mybatis.mapper.UserResultMapMapper">
<select id="queryAllUser" resultType="User_ResultMap">
select * from user;
</select>
</mapper>
MybatisResultMapTest.java单元测试
public class MybatisResultMapTest {
@Test
public void test1(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession();
UserResultMapMapper mapper = sqlSession.getMapper(UserResultMapMapper.class);
List<User_ResultMap> user_resultMaps = mapper.queryAllUser();
System.out.println(user_resultMaps);
}
}
单元测试执行之后,会发现数据库返回的结果集中和JavaBean属性名称不一致的数据是无法映射 存储到JavaBean中的。
这是就需要使用ResultMap进行手动映射处理。
<!--id:resultmap的唯一标识
type:resultmap的类型,即数据库查询数据封装到哪个实体类对象中
-->
<resultMap id="userResultMap" type="user_ResultMap">
<!--主键关系映射对应 column:数据库查询出来的主键字段的名称 property:实体
类中和数据库查询出来的主键对应的属性的名称-->
<id column="id" property="id"></id>
<!--其他字段关系映射对应-->
<result column="user_name" property="un"></result>
<result column="password" property="pw"></result>
</resultMap>
在查询语句中将resultType换成resultMap
<select id="queryAllUser" resultMap="userResultMap">
select * from user;
</select>
如果遇到单纯字段名和属性名不对应的情况,使用别名的方式更简单
<!--明知道数据库表查询字段和实体类属性名称不对应,但是就是使用resulttype去封装处
理数据,怎么保证数据全部查询封装起来-->
<select id="queryAll" resultType="user_ResultMap">
select id,user_name un,password pw from user
</select>
2. PageHelper分页的插件
概述
PageHelper非Mybatis官方提供,是开源社区的开发者自己编写的一个用于完成分页查询的 Mybatis插件,开源在Github中。
使用方法
- 添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
-
在Mybatis核心配置文件中配置插件
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 如果当前页超出合法范围,是否返回正确结果 --> <property name="reasonable" value="true"/> <!-- 如果每页显示条数传入0,是否返回所有数据(不分页) --> <property name="pageSizeZero" value="true"/> </plugin> </plugins>
-
PageHelperMapper.java接口中
public interface PageHelperMapper { public List<User> pageQueryUser(); }
-
PageHelperMapper.xml配置文件中
<select id="pageQueryUser" resultType="user"> select * from user </select>
-
调用分页方法
public class PageHelperTest { @Test public void test1(){ SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml"); SqlSession sqlSession = sqlSessionFactory.openSession(); PageHelperMapper mapper =sqlSession.getMapper(PageHelperMapper.class); PageHelper.startPage(2,3); Page<User> page= (Page<User>) mapper.pageQueryUser(); System.out.println(page); } }
会发现使用PageHelper进行分页查询时,获取的数据被封装到Page中。
获取分页参数
在调用了分页方法之后再执行查询操作,返回结果的实际类型其实是 com.github.pagehelper.Page 类型,由于该类型继承了ArrayList,所以我们可以使用List接收。
Page类型封装了分页插件给我们计算好的所有分页参数
Page{count=true, pageNum=703, pageSize=100, startRow=70200, endRow=70300,
total=70238, pages=703, reasonable=true, pageSizeZero=true}
比如我们像下面这样获取总记录数和总页数
public class PageHelperTest {
@Test
public void test1(){
SqlSessionFactory sqlSessionFactory = MybatisUtil.getSqlSessionFactory("Map-Config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession();
PageHelperMapper mapper =sqlSession.getMapper(PageHelperMapper.class);
//方式一
//PageHelper.startPage(2,3);
//Page<User> page= (Page<User>) mapper.pageQueryUser();
//方式二
Page<User> page = PageHelper.startPage(2, 3).doSelectPage(new ISelect() {
@Override
public void doSelect() {
mapper.pageQueryUser();
}
});
//获取总条数
long total = page.getTotal();
//获取总页数
int pages = page.getPages();
//获取每页显示条数
int pageSize = page.getPageSize();
//获取当前页
int pageNum = page.getPageNum();
//获取查询结果
List<User> user = page.getResult();
System.out.println(user);
System.out.println(total+":"+pages+":"+pageSize+":"+pageNum);
}
}
分页插件配置项(可选)
分页插件所有参数都是可选的,我们一般不配置参数。
下面列举了一些可能会用到的参数:
- pageSizeZero :默认值为 false ,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果 仍然是 Page 类型)。
- reasonable :分页合理化参数,默认值为 false 。当该参数设置为 true 时, pageNum<=0 时会查询第一页, pageNum>pages (超过总数时),会查询最后一页。默认 false 时,直接根据参数进行查询。
标签:03,UserMapper,public,sqlSession,user,MyBatis02,id,User From: https://www.cnblogs.com/jiabaolatiao/p/17525057.html要查看所有支持的参数参见:https业github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md