MyBatis(3)-映射文件
本次博文有疑问,请先看MyBatis(1)-简单入门 和 MyBatis(2)-全局配置文件!
如在有疑问,请留言或者咨询博主,博主每天都在!谢谢!
映射文件:
主要是在xxxmapper.xml文件里的配置
映射文件指导这MyBatis如何进行数据库的增删该查,有着很重要的意义。
下面开始进入正题,最后会发一个完整版的代码
因为实现的主要内容是增删改查,所以我们现在接口类中定义好相关的方法,后面不在进行单一的定义!
工程的目录如下:
EmployeeMapper.java
package com.MrChengs.dao; import java.util.Map; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import com.MrChengs.bean.Employee; public interface EmployeeMapper {
//我们直接传入map public Employee getByMap(Map<String,Object> map); //查询满足两个条件的数据 public Employee getByIdAndNames(@Param("id")int id,@Param("name")String name); //查询 public Employee getEmployee(int id); //增加 public void addEmp(Employee employee); //更新 public void updateEmp(Employee employee); //删除 public void deleteById(int id); }
1)insert-映射插入语句
1.1)EmployeeMapper.xml
<insert id="addEmp" >
insert into test(name,gender,email) values(#{name},#{gender},#{email})
</insert>
@Test public void test2() throws IOException{ //1.得到SqlSeesionFactory SqlSessionFactory sessionFactory = getSqlSessionFactory(); //2.得到SqlSession SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = (EmployeeMapper) sqlSession.getMapper(EmployeeMapper.class); //手动添加数据: Employee em = new Employee( "zhangsan", "boy", "zhangsan@qq.com"); mapper.addEmp(em); //手动提交数据 sqlSession.commit(); }finally{ sqlSession.close(); }}
1.3)测试成功
2)update映射更新语句
2.1)EmployeeMapper.xml
<update id="updateEmp"> update test set name=#{name},gender=#{gender} where id=#{id} </update>
2.2)测试类中
@Test public void test3() throws IOException{ //1.得到SqlSeesionFactory SqlSessionFactory sessionFactory = getSqlSessionFactory(); //2.得到SqlSession SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = (EmployeeMapper) sqlSession.getMapper(EmployeeMapper.class); //手动添加数据: Employee em = new Employee( 6,"Jerry", "gril", null); mapper.updateEmp(em); //手动提交数据 sqlSession.commit(); }finally{ sqlSession.close();}}
2.3)测试成功!
3)delete-映射删除操作
3.1)EmployeeMapper.xml
<delete id="deleteById"> delete from test where id=#{id} </delete>
3.2)测试类中
@Test public void test4() throws IOException{ //1.得到SqlSeesionFactory SqlSessionFactory sessionFactory = getSqlSessionFactory(); //2.得到SqlSession SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = (EmployeeMapper) sqlSession.getMapper(EmployeeMapper.class); //手动添加数据: mapper.deleteById(6); //手动提交数据 sqlSession.commit(); }finally{ sqlSession.close();}}
3.3)测试成功!
4)关于主键的值问题
有时候需要用到主键值的问题,所以我们需要去学习这个知识点!
4.1)EmployeeMapper.xml
<!-- useGeneratedKeys="true"使用自增主键获取主键的值 -->
<!-- keyProperty=""接受对应的主键值-->
<insert id="addEmp" useGeneratedKeys="true" keyProperty="id">
insert into test(name,gender,email) values(#{name},#{gender},#{email})
</insert>
4.2)测试类
@Test public void test2() throws IOException{ //1.得到SqlSeesionFactory SqlSessionFactory sessionFactory = getSqlSessionFactory(); //2.得到SqlSession SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = (EmployeeMapper) sqlSession.getMapper(EmployeeMapper.class); //手动添加数据: Employee em = new Employee( "zhangsan", "boy", "zhangsan@qq.com"); mapper.addEmp(em); //获取主键值的属性值进行打印 System.out.println(em.getId()); //手动提交数据 sqlSession.commit(); }finally{ sqlSession.close(); } }
4.3)测试成功
5)参数处理
5.1)单个参数:MyBatis不会做任何处理
#{参数名} : 取出参数值
5.1.1)xml配置文件中
<select id="getId" resultType="com.MrChengs.bean.Employee"> select id,name,gender,email from test where id = #{idabc} </select>
5.1.2)测试类
@Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try{ Employee employee = session.selectOne("getId",5); System.out.println(employee); }finally{ session.close(); } }
5.1.3)测试是成功的!
5.2)多个参数时
MyBatis会做特殊的处理
多个参数时封装成map
key param1 ,param2......
value 传入的值
5.2.1)接口类中的查询代码设计如上所展示的
public Employee getByIdAndNames(@Param("id")int id,@Param("name")String name);
此时去掉@param:
public Employee getByIdAndNames(int id,String name);
5.2.2) xml文件
<select id="getByIdAndNames" resultType="com.MrChengs.bean.Employee" > select id,name,gender,email from test where id = #{id} and name=#{name} </select>
5.2.3)测试代码
@Test public void test5() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getByIdAndNames(5, "MrChengs"); System.out.println(employee); }finally{ sqlSession.close(); } }
5.2.4)此时会报错
5.2.5)处理方案:是在EmployeeMapper.xml文件中修改的
<!-- 同时使用两个参数进行数据库的查询 --> <!-- public Employee getByIdAndNames(int id,String name); --> <select id="getByIdAndNames" resultType="com.MrChengs.bean.Employee" > select id,name,gender,email from test where id = #{param1}
and name=#{param2}
</select>
此时得到正确的答案!
5.3)多个查询字段时推荐使用的命名字段
public Employee getByIdAndNames(@Param("id")int id,@Param("name")String name);
5.3.2)xml文件中
<select id="getByIdAndNames" resultType="com.MrChengs.bean.Employee" > select id,name,gender,email from test where id = #{id} and name=#{name} </select>
public Employee getByMap(Map<String,Object> map);
5.4.2)xml文件中添加
<select id="getByMap" resultType="com.MrChengs.bean.Employee" > select id,name,gender,email from test where id = #{id} and name=#{name} </select>
5.4.3)测试类
@Test public void test6() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Map<String, Object> map = new HashMap<>(); map.put("id", 5); map.put("name", "MrChengs"); Employee employee = mapper.getByMap(map); System.out.println(employee); }finally{ sqlSession.close(); } }
运行时,可以正确输出结果!
5.5)思考问题注意
6).参数值的获取
#{ }:可以获取map中的值,或者pojo对象中的属性值,只能是参数部分的
${ }:可以获取map中的值,或者pojo对象中的属性值,还可是查询中的数据表
B:在全局配置里面(Oracle&MySql都课识别)
<!-- 修改全局信息 -->
<settings> <setting name="jdbcTypeForNull" value="NULl"/> </settings>
//返回集合 public List<Employee> getByList(String name);
在xml文件中:
<!-- 返回值是集合 --> <!-- resultType:如果返回值是一个集合,要写集合中的元素类型 --> <!-- 模糊查询 --> <!-- 此时查询的类型还是Emoloyee类的 --> <select id="getByList" resultType="com.MrChengs.bean.Employee"> select * from test where name like #{name} </select>
实现类:
@Test public void testList() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); List<Employee> name = mapper.getByList("%Mr%"); for(Employee em : name){ System.out.println(em); } }finally{ sqlSession.close(); } }
数据库&结果图
B.把单个数据封装成map
接口类:
//返回一条记录的map, key是列名,值是对应的值 public Map<String,Object> getByIdReturnMap(int id);
xml文件:
<!-- 单个数据封装成map --> <!-- public Map<String,Object> getByIdReturnMap(int id); --> <select id="getByIdReturnMap" resultType="map"> select * from test where id=#{id} </select>
实现类:
@Test public void testgetByIdReturnMap() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); Map<String,Object> map = mapper.getByIdReturnMap(5); System.out.println(map); }finally{ sqlSession.close(); } }
结果:
C.把多个结果封装成map
接口类:
//多个记录封装成一个map Map<int,Employee>,键是记录的主键,值是封装的值 //告诉mybatis封装map使用那个属性作为map的key //若改为name,则name为key @MapKey("id") public Map<Integer,Employee> getByNameMap(String name);
xml文件:
1 <select id="getByNameMap" resultType="com.MrChengs.bean.Employee"> 2 select * from test where name like #{name} 3 </select>
实现类:
@Test public void testByMapName() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class) Map<Integer,Employee> ems = mapper.getByNameMap("%M%"); System.out.println(ems); }finally{ sqlSession.close(); } }
结果:
D).resultMap自定义查询
在EmployeeMapperTwo.java接口类:
//resultMap自定义结果映射 public Employee getById(Integer id);
在全局配置文件中进行引入:mybatis-config.xml(博主当时没引入,一致忽略这个问题,手动查询问题好久)
<mappers> <mapper resource="EmployeeMapper.xml" /> <mapper resource="EmployeeMapperTwo.xml"/> </mappers>
<!-- 自定义某个javaBean的封装规则 --> <!-- type:是全类名,也可以是起的别名 --> <!-- id:唯一性便于引用 --> <resultMap type="com.MrChengs.bean.Employee" id="MyEmp"> <!-- 指定主键列的封装规则 --> <!-- id:定义主键会底层优化 --> <!-- column:指定那一列 --> <!-- property:指定对应的JavaBean属性 --> <id column="id" property="id"/> <!-- 定义普通列封装规则 --> <result column="name" property="name"/> <!-- 其他不指定的列会自动封装 --> <!-- 但是建议所有的都写出来,便于后期的维护和检查 --> <result column="gender" property="gender"/> <result column="email" property="email"/> </resultMap> <!-- public Employee getById(Integer id); --> <!-- resultMap自定义自定义结果映射 --> <!-- 使用resultMap则不能使用resultType两者只能二选一 --> <select id="getById" resultMap="MyEmp"> select * from test where id=#{id} </select>
测试类中:
//resultMap自定义结果映射 //public Employee getById(Integer id); @Test public void testResultMap() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapperTwo mapper1 = sqlSession.getMapper(EmployeeMapperTwo.class); Employee emp = mapper1.getById(5); System.out.println(emp); }finally{ sqlSession.close(); } }
得到查询的结果:
alter table user add foreign key(d_id) references tbl_dept(id);
在数据库中查询两个表
SELECT * FROM test e,tbl_dept d
where e.d_id=d.id AND e.id=5
方法一:
数据库查询进一步优化方案:
SELECT e.id id,e.name,e.gender gender,e.email email,e.d_id d_id,d.dept_name dept
FROM test e,tbl_dept d
where e.d_id=d.id AND e.id=5
//场景一查询Employee同时查询Deapment public Employee getEmpAndDept(int id);
xml文件中:
<!-- 查询员工对应的部门信息 --> <!-- public Employee getEmpAndDept(Integer id); --> <!-- 结果集封装 --> <resultMap type="com.MrChengs.bean.Employee" id="MyEmpMangTable"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="gender" property="gender"/> <result column="email" property="email"/> <!-- 级联属性的赋值方式!!! --> <result column="d_id" property="dept.id"/> <!-- 级联属性的赋值方式!!! --> <result column="dept_name" property="dept.departName"/> </resultMap> <select id="getEmpAndDept" resultMap="MyEmpMangTable"> SELECT e.id id,e.name name,e.gender gender,e.email
email,e.d_id d_id,d.dept_name dept_name FROM test e,tbl_dept d where e.d_id=d.id AND e.id=#{id} </select>
实现的方法:
//场景一:查询Employee的同时查询员工对应的部门 // Employee ---.> Department //一个员工与之对应的部门信息 @Test public void testAndDept() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapperTwo mapper = sqlSession.getMapper(EmployeeMapperTwo.class); Employee emp = mapper.getEmpAndDept(5); System.out.println(emp); System.out.println(emp.getDept()); }finally{ sqlSession.close(); } }
查询结果:(可以同上上面的数据库进行对比)
<!-- 不使用级联属性 --> <resultMap type="com.MrChengs.bean.Employee" id="MyEmpMangTable1"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="gender" property="gender"/> <result column="email" property="email"/> <!-- association:联合的意思,可以联合JavaBean对象 --> <!-- property="dept":指定那个是联合的对象 --> <!-- javaType="com.MrChengs.bean.Department": 指定这个属性对象的类型 --> <association property="dept" javaType="com.MrChengs.bean.Department"> <!--此时再次类似resultMap标签 --> <!-- 此时的对象是Department --> <id column="d_id" property="id"/> <result column="dept_name" property="departName"/> </association> </resultMap> <select id="getEmpAndDept" resultMap="MyEmpMangTable1"> SELECT e.id id,e.name name,e.gender gender,e.email email,
e.d_id d_id,d.dept_name dept_name FROM test e,tbl_dept d where e.d_id=d.id AND e.id=#{id} </select>
其他方法不变,依然可以查出结果!!!!
public interface DepartmentMapper { public Department getDeptById(int id); }
DepartmentMapper.xml
<mapper namespace="com.MrChengs.dao.DepartmentMapper"> <!-- public Department getDeptById(int id); --> <select id="getDeptById" resultType="com.MrChengs.bean.Department"> select id,dept_name departName from tbl_dept where id=#{id} </select> </mapper>
解释:这两个文件其实是一个简单查询的过程
<!-- association:可以进行封闭查询 --> <!-- public Employee getEmpAndDeptByStep(int id); --> <resultMap type="com.MrChengs.bean.Employee" id="MyEmpByStep"> <!-- 1.先查出员工信息 --> <id column="id" property="id"/> <result column="name" property="name"/> <result column="gender" property="gender"/> <result column="email" property="email"/> <!-- association 定义关联关系的封装对象 --> <!-- select: 调用当前属性指定的方法查出结果--> <!-- column:指定将那个值传递给这个方法 --> <association property="dept" select="com.MrChengs.dao.DepartmentMapper.getDeptById" <!-- 传值 --> column="d_id"></association> </resultMap> <select id="getEmpAndDeptByStep" resultMap="MyEmpByStep"> select * from test where id=#{id} </select>
3.测试类:
//分布查询 @Test public void testAndDeptByStep() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ EmployeeMapperTwo mapper = sqlSession.getMapper(EmployeeMapperTwo.class); Employee emp = mapper.getEmpAndDept(5); System.out.println(emp); System.out.println(emp.getDept()); }finally{ sqlSession.close(); } }
<settings> <!-- 显示的指定我们需要更改的配置信息,防止版本更新带来的问题 --> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
SELECT d.id,d.dept_name dept,e.id id,e.name,e.gender gender,e.email email,e.d_id d_id
FROM test e,tbl_dept d
where e.d_id=d.id AND d.id=1;
在Department类中:
在DepartmentMapper.xml文件中:
<!-- public Department getDeptByIds(int id); --> <!-- 查询部门同时查看出部门里面的员工 --> <resultMap type="com.MrChengs.bean.Department" id="employees"> <id column="id" property="id"/> <result column="dept" property="departName"/> <!-- collection:定义集合对象 --> <!-- ofType:指定测试集合的类型 --> <!-- property:定义对象的原型属性,即是我们在类中的定义方法 --> <collection property="employees" ofType="com.MrChengs.bean.Employee"> <!-- 定义集合封装规则 --> <id column="id" property="id"/> <result column="name" property="name"/> <result column="gender" property="gender"/> <result column="email" property="email"/> </collection> </resultMap> <select id="getDeptByIds" resultMap="employees"> SELECT d.id id,d.dept_name dept, e.id id,e.name name,e.gender gender,e.email email FROM test e,tbl_dept d where e.d_id=d.id AND d.id=#{id} </select>
//查询部门时查员工 public Department getDeptByIds(int id);
测试类中:
//场景二: //在查询部门信息的时候,查询员工信息 //分布查询 @Test public void testEmps() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ DepartmentMapper mapper = sqlSession.getMapper(DepartmentMapper.class); Department dept = mapper.getDeptByIds(1); System.out.println(dept); System.out.println(dept.getEmployees()); }finally{ sqlSession.close(); } }
相当于一个嵌套查询
//collection分布查询 public Department getDeptByIdsByStep(int id);
EmployeeMapperTwo.java
//collection分布实现 public List<Employee> getEmpByStep(int id);
<!-- collection分布查询 --> <!-- public List<Employee> getEmpByStep(int id); --> <select id="getEmpByStep" resultType="com.MrChengs.bean.Employee"> select * from test where d_id=#{d_id} </select>
DepartmentMapper.xml
<!-- 分布实现 --> <!-- public Department getDeptByIdsByStep(int id); --> <!-- collection分布实现 --> <resultMap type="com.MrChengs.bean.Department" id="MyStept"> <id column="id" property="id"/> <result column="departName" property="departName"/> <collection property="employees" select="com.MrChengs.dao.EmployeeMapperTwo.getEmpByStep" column="id"> </collection> </resultMap> <select id="getDeptByIdsByStep" resultMap="MyStept"> select id,dept_name departName from tbl_dept where id=#{id} </select>
实现类
//collection 分布实现 @Test public void testEmpsStep() throws IOException{ SqlSessionFactory sessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sessionFactory.openSession(); try{ DepartmentMapper mapper = sqlSession.getMapper(DepartmentMapper.class); Department dept = mapper.getDeptByIdsByStep(1); System.out.println(dept); System.out.println(dept.getEmployees()); }finally{ sqlSession.close(); } }