一、MyBatis获取参数值的两种方式:${}和#{}
1、${}的本质就是字符串拼接,#{}的本质就是占位符赋值
2、${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;
3、#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时, 可以自动添加单引号。
二、各种查询功能
1、单个字面量类型的参数
若mapper接口中的方法参数为单个的字面量类型,此时可以使用${}和#{}以任意的名称获取参数的值,注意${}需要手动加单引号
(单个字面量类型:8个基本数据类型+字符串类型)
接口:
package com.softeem.mapper;
import com.softeem.bean.User;
public interface UserMapper {
/**
* 根据用户id查询用户信息
* @param id
* @return
*/
User getUserById(int id);
}
xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.softeem.mapper.UserMapper">
<select id="getUserById" resultType="com.softeem.bean.User">
select * from t_user where id = #{id}
</select>
</mapper>
=========================================================================
注意:若在此处使用${id}无论是否添加单引号,结果一样,因为此处使用的是id查询,而id是一个数字,在MySQL查询中是否添加单引号都可以查出来
但是其他的字符类型,如varchar类型,则必须添加单引号
=========================================================================
测试类:
package com.softeem.test;
import com.softeem.bean.User;
import com.softeem.mapper.UserMapper;
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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class UserTest {
SqlSession sqlSession = null;
@Before
public void init() throws IOException {
//读取MyBatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
//SqlSession sqlSession1 = sqlSessionFactory.openSession(false);
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
sqlSession= sqlSessionFactory.openSession(true);
}
@Test
public void getUserByIdTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(11);
System.out.println(user);
}
}
测试结果:
2、多个字面量类型的参数
若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1...为键,以参数为值;
以param1,param2...为键,以参数为值;
因此只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号。
接口:
/**
* 根据用户名查询用户信息
* @param username
* @param password
* @return
*/
User getUserByNameAndPassword(String username,String password);
xml文件:
<select id="getUserByNameAndPassword" resultType="user">
select * from t_user where username = #{arg0} and password = #{arg1}
</select>
<!-- 或者
<select id="getUserByNameAndPassword" resultType="user">-->
<!-- select * from t_user where username = #{param1} and password = #{param2}-->
<!-- </select>-->
测试类:
@Test
public void getUserByNameAndPasswordTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserByNameAndPassword("ybc","123");
System.out.println(user);
}
得到结果为:
=========================================================================
(该使用使用较少)或者,可以将参数封装到一个Map集合内,通过调用集合内值的操作达到效果:
得到结果为:
=========================================================================
=========================================================================
(*常用,推荐此方法)或者:在接口处,对方法内参数使用注解
接口:
/**
* 根据用户名查询用户信息
* @param username
* @param password
* @return
*/
User getUserByNameAndPassword(@Param("username")String username,
@Param("password")String password);
xml文件:
<select id="getUserByNameAndPassword" resultType="user">
select * from t_user where username = #{username} and password = #{password}
</select>
测试类:
@Test
public void getUserByNameAndPasswordTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserByNameAndPassword("ybc","123");
System.out.println(user);
}
测试结果:
注意事项:
3、实体类类型的参数
若mapper接口中的方法参数为实体类对象时,可以使用${}和#{},通过访问实体类对象中的属性名获取属性值,注意${}需要手动加单引号。
接口:
/**
* 保存用户信息
* @param user
* @return
*/
int insertUser(User user);
xml文件:
<insert id="insertUser">
insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
测试类:
@Test
public void insertUserTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("zhangsan");
user.setPassword("111");
user.setAge("18");
user.setSex("男");
user.setEmail("123789@qq.com");
userMapper.insertUser(user);
}
得到结果为:
4、进阶版小练习
接口:
/**
* 分页查询用户信息
* @param user
* @param start
* @param end
* @return
*
* Map map = new HashMap();
* map.put("user", user);
* map.put("start", 0);
* map.put("end", 5);
*/
List<User> pageUser(@Param("user") User user,@Param("start")int start,@Param("end")int end);
xml文件:
<select id="pageUser" resultType="com.softeem.bean.User">
select * from t_user where username like concat('%',#{user.username},'%') limit #{start},#{end}
</select>
测试类:
@Test
public void pageUserTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("a");
List<User> userList = userMapper.pageUser(user, 0, 5);
userList.forEach(System.out::println);
}
得到结果为:
(数据库表截图:)
练习总结:
如果是多个参数,可能有对象,自变量。不管是什么类型,只要是有多个参数,就用注解,最终生成一个map集合。然后在SQL语句里面取值的时候,就通过map集合的key取值,再通过user对象调username,就到了这个username的值。
5、TooManyResultsException异常处理
当查询的数据为多条时,不能使用实体类作为返回值,否则会抛出异常TooManyResultsException;
但是若查询的数据只有一条,可以使用实体类或集合作为返回值
接口:
/** 查询所有用户信息
* @return
*/
User findAll();
xml文件:
<select id="findAll" resultType="com.softeem.bean.User">
select * from t_user
</select>
测试类:
@Test
public void findAllTest() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findAll();
System.out.println("userList = " + user);
}
得到结果为: