二、Mybatis的映射文件
1、Dao层的接口
public interface EmployeeMapper {
/**
* 根据id查询employee
* @param id
* @return
*/
Employee SelectEmpById(int id);
/**
* 根据id值和lastName查询employee
* 方法传递多个参数时:Mybatis会做一些特殊处理
* Available parameters are [arg1, arg0, param1, param2]
* 多个参数会被封装为一个map
* key : param1...paramN
* value : 传递的参数值
* #{}就是从map中获取指定key的值
* 也就是说我们不做处理的时候我们的sql语句要这么写才可以:
* select * from tbl_employee where id = #{param1} and last_name = #{param2}]
* 解决办法:
* 在方法形参加上 @param注解指定映射的值
*/
Employee SelectEmpByIdAndLastName(@Param("id") int id,@Param("lastName") String lastName);
/**
* 使用map封装id和lastName进行查询
* @param map
* @return
*/
Employee selectEmpByMap(Map<Object,Object> map);
/**
* 插入一条记录
* @param emp
*/
void insertEmp(Employee emp);
/**
* 根据id删除员工
* @param id
* @return
*/
boolean deleteEmpById(Integer id);
/**
* 修改一个员工
* @param emp
* @return
*/
int updateEmp(Employee emp);
2、Mybatis的sql映射文件
<?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="day01.mapper.EmployeeMapper">
<!-- Employee SelectEmpById(int id);-->
<select id="SelectEmpById" resultType="day01.domain.Employee">
select * from tbl_employee where id = #{id}
</select>
<!-- void insertEmp(Employee emp);-->
<!-- parameterType属性一般省略-->
<!-- 获取自增主键的值-->
<!-- mysql支持主键的自增,自增注解值的获取,mybatis也是利用statement.getGeneratedKeys()获取主键值的-->
<!-- useGeneratedKeys="true" : 使用自增主键获取主键值策略-->
<!-- keyProperty : 指定对应的主键属性,也就是mybatis获取到主键值后,将这个值封装给javaBean对象的那个属性-->
<insert id="insertEmp" parameterType="day01.domain.Employee" useGeneratedKeys="true" keyProperty="id">
insert into
tbl_employee(last_name,gender)
values(#{lastName},#{gender})
</insert>
<!-- boolean deleteEmpById(Integer id);-->
<delete id="deleteEmpById">
delete from
tbl_employee
where
id = #{id}
</delete>
<!-- int updateEmp(Employee emp);-->
<update id="updateEmp">
update
tbl_employee
set
last_name = #{lastName},
gender = #{gender}
where
id = #{id}
</update>
<!-- Employee SelectEmpByIdAndLastName(int id,String lastName);-->
<!-- 当传递一个参数时Mybatis不会做任何处理,可以直接查询-->
<!-- 当我们传递多个参数时,Mybatis会封装为一个map集合-->
<select id="SelectEmpByIdAndLastName" resultType="day01.domain.Employee">
select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>
<!-- Employee selectEmpByMap(Map<Object,Object> map);-->
<select id="selectEmpByMap" resultType="day01.domain.Employee">
select * from tbl_employee where id = #{id} and last_name = #{lastName}
</select>
</mapper>
3、增删改查的测试
/**
* 测试查看数据
* @throws IOException
*/
@Test
public void test1() throws IOException {
//1.找到文件路径
String resource = "MybatisConfig.xml";
//2.将文件加载进内存
InputStream inputStream = Resources.getResourceAsStream(resource);
//3.通过SqlSessionFactoryBuilder构建SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//4.通过sqlSessionFactory获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//5.sqlSession负责执行sqlSession是线程不安全的
try{
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee emp = mapper.SelectEmpById(1);
System.out.println(emp);
}finally {//关闭是必须操作
sqlSession.close();
}
}
/**
* 测试增加数据
*/
@Test
public void test2(){
SqlSession session = MybatisUtils.getSession();
try{
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Employee emp = new Employee();
//赋值的时候没有指定主键,利用mysql的自增属性
emp.setLastName("李四");
emp.setGender("女");
mapper.insertEmp(emp);
//因为配置了mybatis的useGeneratedKeys属性,将自增的主键值反向赋值给了javaBean对象
System.out.println(emp);
//提交数据
session.commit();
}finally {
session.close();
}
}
/**
* 测试修改数据
*/
@Test
public void test3(){
SqlSession session = MybatisUtils.getSession();
try{
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Employee emp = new Employee();
emp.setId(1);
emp.setLastName("王五");
emp.setGender("女");
int i = mapper.updateEmp(emp);
System.out.println(i);
session.commit();
}finally {
session.close();
}
}
/**
* 测试删除数据
*/
@Test
public void test4(){
SqlSession session = MybatisUtils.getSession();
try{
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
boolean flag = mapper.deleteEmpById(3);
System.out.println(flag);
session.commit();
}finally {
session.close();
}
}
4、关于数据提交
* 1.Mybatis允许增删改直接定义以下类型返回值
* Integer Long Boolean void 以及对应的基本数据类型 Mybatis会自动判断和接收
* 2.我们需要手动提交数据
* sqlSessionFactory.openSession(); ===> 手动提交数据
* sqlSessionFactory.openSession(true); ===> 自动提交数据
5、多个参数的映射问题
/**
* 多个参数时Mybatis的映射
* 根据id值和lastName查询employee
* 方法传递多个参数时:Mybatis会做一些特殊处理
* Available parameters are [arg1, arg0, param1, param2]
* 多个参数会被封装为一个map
* key : param1...paramN
* value : 传递的参数值
* #{}就是从map中获取指定key的值
* 也就是说我们不做处理的时候我们的sql语句要这么写才可以:
* select * from tbl_employee where id = #{param1} and last_name = #{param2}]
* 解决办法:
* 在方法形参加上 @param注解指定映射的值
*/
@Test
public void test5(){
SqlSession session = MybatisUtils.getSession();
try{
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Employee emp = mapper.SelectEmpByIdAndLastName(1, "王五");
System.out.println(emp);
session.commit();
}finally {
session.close();
}
}
/**
* 传递多个参数时,可以观察到上述使用@Param注解的方法比较麻烦
* 使用一下方式传递多个参数
* 1.POJO
* 如果多个参数正好是我们业务逻辑的数据模型,我们可以直接传入POJO
* #{属性名} : 取出传入的POJO的属性值
* 2.Map
* 如果多个参数不是模型中的数据,没有对应的POJO,不经常使用的情况下,可以传入一个Map
* #{key} : 取出map中对应的value值
* 3.TO
* 如果不是业务模型中的数据,但是经常使用,推荐编写一个TO(Transfer Object) 例如:pageBean对象
* 使用分页查询时经常使用
*/
/**
* 演示map的使用
*/
@Test
public void test6(){
SqlSession session = MybatisUtils.getSession();
try{
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Map<Object,Object> map = new HashMap<>();
map.put("id",1);
map.put("lastName","王五");
Employee emp = mapper.selectEmpByMap(map);
System.out.println(emp);
}finally {
session.close();
}
}
6、关于#{}取值的一些问题
/**
* 思考以下问题如何获取值 #{}
* public Employee getEmp(@Param("id") Integer id,String lastName);
* 取值 : id ==> #{id/param1} lastName ==> #{param2}
* public Employee getEmp(Integer id,@Param("e")Employee emp);
* 取值 : id ==> #{param1} lastName ==> #{param2.lastName/e.lastName}
* 如果是Collection(List,Set)类型或者是数组默认的key不再是 param 而是一下类型
* Mybatis也会做特殊处理。会把List集合或数组封装在map中
* key : Collection 的key是 collection
* List 的key是 list
* 数组 的key是 array
* 例子:public Employee getEmpById(List<Integer> ids);
* 取值 : 取出第一个id值 #{list[0]} 注意并不是 #{ids[0]} 集合 数组同理
*
*/
7、#{} 和 ${}的区别
/**
* #{} 和 ${} 取值的区别:
* #{} : 是以预编译的形式,将参数sql语句中,jdbc中的PrepareStatement : 防止sql注入
* ${} : 是以值的拼接在sql语句中的,会有安全问题
* 大多数情况下我们使用的是 #{}
* 我们使用${}的场景:
* 原生的jdbc不支持占位符的地方我们就可以使用${}进行取值
* 例如:
* 分表、分组语句...:
* select * from ${tableName};
* 此时就只能使用${} 因为 表名这个位置 jdbc并不支持占位符的操作类似还有group by 等
*/