八、MyBatis工具类【重点


8.1 封装工具类

  • Resource:用于获得读取配置文件的IO对象,耗费资源,建议通过IO一次性读取所有所需要的数据。

  • SqlSessionFactory:SqlSession工厂类,内存占用多,耗费资源,建议每个应用只创建一个对象。

  • SqlSession:相当于Connection,可控制事务,应为线程私有,不被多线程共享。

  • 将获得连接、关闭连接、提交事务、回滚事务、获得接口实现类等方法进行封装。

package com.qf.mybatis.part1.utils;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 java.io.InputStream;public class MyBatisUtils {//获得SqlSession工厂private static SqlSessionFactory factory;//创建ThreadLocal绑定当前线程中的SqlSession对象private static final ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();static {try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");factory = new SqlSessionFactoryBuilder().build(is);} catch (Exception e) {e.printStackTrace();}}//获得连接(从tl中获得当前线程SqlSession)private static SqlSession openSession(){SqlSession session = tl.get();if(session == null){session = factory.openSession();tl.set(session);}return session;}//释放连接(释放当前线程中的SqlSession)private static void closeSession(){SqlSession session = tl.get();session.close();tl.remove();}//提交事务(提交当前线程中的SqlSession所管理的事务)public static void commit(){SqlSession session = openSession();session.commit();closeSession();}//回滚事务(回滚当前线程中的SqlSession所管理的事务)public static void rollback(){SqlSession session = openSession();session.rollback();closeSession();}//获得接口实现类对象public static <T extends Object> T getMapper(Class<T> clazz){SqlSession session = openSession();return session.getMapper(clazz);}
}

8.2 测试工具类

调用MyBatisUtils中的封装方法。

@Test
public void testUtils() {try {UserDao userDao = MyBatisUtils.getMapper(UserDao.class);userDao.deleteUser(15);MyBatisUtils.commit();} catch (Exception e) {MyBatisUtils.rollback();e.printStackTrace();}
}

补充:

package com.qf.util;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 java.io.IOException;
import java.io.InputStream;/*** 1. 加载配置* 2. 创建SqlSessionFactory* 3. 创建Session* 4. 事务管理* 5. Mapper获取*/
public class MyBatisUtil {//先做一个静态的sqlSessionFactoryprivate static SqlSessionFactory sqlSessionFactory;private static final ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();//sqlSessionFactory 需要加载配置的支持,因为只需要加载一次,那就使用静态代码块static{//加载配置信息try {//1.获得读取MyBatis配置文件的流对象InputStream is = Resources.getResourceAsStream("mybatis-config.xml");//2.构建SqlSession连接对象的工厂sqlSessionFactory  = new SqlSessionFactoryBuilder().build(is);} catch (IOException e) {e.printStackTrace();}}//sqlSession和jdbc中的connection一样// 要保证线程唯一,全局不唯一的特点->需要ThreadLocal//通过下面spenSession方法可以让线程绑定一个session,不需要重复创建public static SqlSession openSession(){SqlSession sqlSession = tl.get();//看当前线程中是否绑定好了sessionif(sqlSession==null){sqlSession=sqlSessionFactory.openSession();//sqlsession为空那就绑定新创建的tl.set(sqlSession);//set绑定再该线程中}return sqlSession;}//关闭sqlsession资源public static void closeSession(){SqlSession sqlSession = tl.get();sqlSession.close();}//事务提交public static void commit(){SqlSession sqlSession = openSession();//拿到当前线程绑定的sessionsqlSession.commit();closeSession();}public static void rollback(){SqlSession sqlSession = openSession();sqlSession.rollback();closeSession();}//Mapper的获取,返回mapper实现类对象,所以不一样,使用泛型,返回T//参数是一个类对象//也就是给一个XXXDAO就返回XXXpublic static <T> T getMapper(Class<T> mapper){SqlSession sqlSession = openSession();return sqlSession.getMapper(mapper);}}

测试:

package com.qf;import com.qf.dao.StudentDAO;
import com.qf.entity.Student;
import com.qf.util.MyBatisUtil;public class TestMyBatis {public static void main(String[] args) {//StudentStudentDAO studentmapper = MyBatisUtil.getMapper(StudentDAO.class);studentmapper.insertStudent(new Student(null,"zhangsan",true));System.out.println(studentmapper);MyBatisUtil.commit();MyBatisUtil.closeSession();}
}

九、ORM映射【重点


9.1 MyBatis自动ORM失效

MyBatis只能自动维护库表”列名“与”属性名“相同时的一一对应关系,二者不同时,无法自动ORM。

自动ORM失效

9.2 方案一:列的别名

在SQL中使用 as 为查询字段添加列别名,以匹配属性名。

<mapper namespace="com.qf.mybatis.part2.orm.ManagerDao"><select id="selectManagerByIdAndPwd" resultType="com.qf.mybatis.part2.orm.Manager">SELECT mgr_id AS id , mgr_name AS username , mgr_pwd AS passwordFROM t_managersWHERE mgr_id = #{id} AND mgr_pwd = #{pwd}</select>
</mapper>

9.3 方案二:结果映射(ResultMap - 查询结果的封装规则)

通过< resultMap id="" type="" >映射,匹配列名与属性名。

<mapper namespace="com.qf.mybatis.part2.orm.ManagerDao"><!--定义resultMap标签--><resultMap id="managerResultMap" type="com.qf.mybatis.part2.orm.Manager"><!--关联主键与列名--><id property="id" column="mgr_id" /><!--关联属性与列名--><result property="username" column="mgr_name" /><result property="password" column="mgr_pwd" /></resultMap><!--使用resultMap作为ORM映射依据--><select id="selectAllManagers" resultMap="managerResultMap">SELECT mgr_id , mgr_name , mgr_pwdFROM t_managers</select>
</mapper>
<?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"><!--namespace = 所需实现的接口全限定名-->
<mapper namespace="com.qf.dao.UserDAO"><resultMap id="user_resultMap" type="User"><!-- 定义更复杂的  映射规则 --><id column="id" property="id"></id><result column="username" property="username"></result><result column="password" property="password"></result><result column="gender" property="gender"></result><result column="regist_time" property="registTime"></result></resultMap><!--id = 所需重写的接口抽象方法,resultType = 查询后所需返回的对象类型--><!--不使用resultType,使用resultMap--><select id="queryUserById" resultMap="user_resultMap">SELECT id,username,password,gender,regist_timefrom t_user where id=#{id}</select></mapper>
        //测试resultMap映射关系UserDAO usermapper = MyBatisUtil.getMapper(UserDAO.class);User user = usermapper.queryUserById(9);System.out.println(user);


测试成功,最后的字符被映射好。

十、MyBatis处理关联关系-多表连接【重点


实体间的关系:关联关系(拥有 has、属于 belong)

  • OneToOne:一对一关系(Passenger— Passport)

  • OneToMany:一对多关系(Employee — Department)

  • ManyToMany:多对多关系(Student — Subject)

Table建立外键关系
Entity添加关系属性
Mapper中将属性与列名对应

10.1 OneToOne–旅客表和护照表

SQL参考OneToOneExample.sql

<mapper namespace="com.qf.mybatis.part2.one2one.PassengerDao"><!-- 结果映射(查询结果的封装规则) --><resultMap id="passengerResultMap" type="com.qf.mybatis.part2.one2one.Passenger"><id property="id" column="id"/><result property="name" column="name" /><result property="sex" column="sex" /><result property="birthday" column="birthday" /><!-- 关系表中数据的封装规则 -->   <!-- 指定关系表的实体类型 --><association property="passport" javaType="com.qf.mybatis.part2.one2one.Passport"><id property="id" column="passport_id" /><result property="nationality" column="nationality" /><result property="expire" column="expire" /><result property="passenger_id" column="passenger_id" /></association></resultMap><!-- 多表连接查询 -->                      <!-- 结果映射(查询结果的封装规则)--><select id="selectPassengerById" resultMap="passengerResultMap"><!-- 别名(避免与p1.id冲突) -->SELECT p1.id , p1.name , p1.sex , p1.birthday , p2.id as passport_id , p2.nationality , p2.expire             , p2.passenger_idFROM t_passengers p1 LEFT JOIN t_passports p2ON p1.id = p2.passenger_idWHERE p1.id = #{id}</select>
</mapper>
  • 注意:指定“一方”关系时(对象),使用< association javaType="" >
    补充代码:
    SQL:
 create table t_passengers(id int primary key auto_increment,name varchar(50),sex varchar(1),birthday date
)default charset =utf8;create table t_passports(id int primary key auto_increment,nationality varchar(50),expire date,passenger_id int unique,foreign key (passenger_id) references t_passengers(id)
)default charset =utf8;insert into t_passengers values(null,'shine_01','f','2018-11-11');
insert into t_passengers values(null,'shine_02','m','2019-12-12');insert into t_passports values(null,'China','2030-12-12',1);
insert into t_passports values(null,'America','2035-12-12',2);

entity

package com.qf.entity;import java.util.Date;//护照类
public class Passport {private Integer id;private String nationality;private Date expire;// 存储旅客信息 : 添加关系属性private Passenger passenger;public Passport(){}public Passport(Integer id, String nationality, Date expire) {this.id = id;this.nationality = nationality;this.expire = expire;}@Overridepublic String toString() {return "Passport{" +"id=" + id +", nationality='" + nationality + '\'' +", expire=" + expire +'}';}public Passenger getPassenger() {return passenger;}public void setPassenger(Passenger passenger) {this.passenger = passenger;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getNationality() {return nationality;}public void setNationality(String nationality) {this.nationality = nationality;}public Date getExpire() {return expire;}public void setExpire(Date expire) {this.expire = expire;}
}
package com.qf.entity;import java.util.Date;//旅客类
public class Passenger {private Integer id;private String name;private Boolean sex;private Date birthday;// 存储旅客的护照信息 : 关系属性private Passport passport;public Passenger(){}public Passenger(Integer id, String name, Boolean sex, Date birthday) {this.id = id;this.name = name;this.sex = sex;this.birthday = birthday;}public Passport getPassport() {return passport;}public void setPassport(Passport passport) {this.passport = passport;}@Overridepublic String toString() {return "Passenger{" +"id=" + id +", name='" + name + '\'' +", sex=" + sex +", birthday=" + birthday +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Boolean getSex() {return sex;}public void setSex(Boolean sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}
}

注意添加关系属性。

dao:

public interface PassengerDAO {Passenger queryPassengerById(@Param("id") Integer id);
}
public interface PassportDAO {Passport queryPassportById(@Param("id") Integer id);
}

Mapper.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.qf.dao.PassengerDAO"><!--使用resultMap作映射,resultTyper='实体类' 实体类和返回值不符--><resultMap id="passenger_passport" type="Passenger"><id column="id" property="id"></id><result column="name" property="name"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result><!-- 描述 passId nationality expire 和  passport 映射规则 --><!--使用association标签作关联属性的映射。--><association property="passport" javaType="Passport"><id column="passId" property="id"></id><result column="nationality" property="nationality"></result><result column="expire" property="expire"/></association></resultMap><!-- 查询 旅客及其护照 --><select id="queryPassengerById" resultMap="passenger_passport">select t_passengers.id,t_passengers.name,t_passengers.sex,t_passengers.birthday,t_passports.id passId,t_passports.nationality,t_passports.expirefrom t_passengers join t_passportson t_passengers.id = t_passports.passenger_idwhere t_passengers.id=#{id}</select></mapper>

<?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.qf.dao.PassportDAO"><resultMap id="passport_passenger" type="Passport"><id column="id" property="id"></id><result column="nationality" property="nationality"></result><result column="expire" property="expire"></result><association property="passenger" javaType="Passenger"><id column="passenger_id" property="id"></id><result column="name" property="name"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result></association></resultMap><select id="queryPassportById" resultMap="passport_passenger">select t_passports.id,t_passports.nationality,t_passports.expire,t_passengers.id passenger_id,t_passengers.name,t_passengers.sex,t_passengers.birthdayfrom t_passports join t_passengerson t_passengers.id = t_passports.passenger_idwhere t_passports.id=#{id}</select></mapper>

注意:需要注册新的mapper.xml文件

    <!--Mapper文件注册位置--><mappers><!--注册Mapper文件--><!--<mapper resource="UserDAOMapper.xml"/>--><mapper resource="com/qf/dao/UserDAOMapper.xml"/><mapper resource="com/qf/dao/StudentDAOMapper.xml"/><mapper resource="com/qf/dao/PassengerDAOMapper.xml"/><mapper resource="com/qf/dao/PassportDAOMapper.xml"/></mappers>

测试:

PassengerDAO mapper = MyBatisUtil.getMapper(PassengerDAO.class);
Passenger passenger = mapper.queryPassengerById(1);
System.out.println("============");
System.out.println(passenger);
System.out.println(passenger.getPassport());//使用get方法,获取对象值

10.2 OneToMany–员工部门关系表

SQL参考OneToManyExample.sql

<mapper namespace="com.qf.mybatis.part2.one2many.DepartmentDao"><!-- 封装规则 --><resultMap id="departmentResultMap" type="com.qf.mybatis.part2.one2many.Department"><id property="id" column="id" /><result property="name" column="name" /><result property="location" column="location" /><!-- 关系表中数据的封装规则 -->       <!-- 指定关系表的实体类型 --><collection property="emps" ofType="com.qf.mybatis.part2.one2many.Employee"><id property="id" column="emp_id" /><result property="name" column="emp_name" /><result property="salary" column="salary" /><result property="dept_id" column="dept_id" /></collection></resultMap><!-- 多表连接查询 -->                 <!-- 封装规则 --><select id="selectDepartmentById" resultMap="departmentResultMap" ><!-- 别名(避免与d.id、d.name冲突)-->SELECT d.id , d.name , d.location , e.id AS emp_id , e.name emp_name , e.salary , e.dept_idFROM t_departments d LEFT JOIN t_employees eON d.id = e.dept_idWHERE d.id = #{id}</select></mapper>
  • 注意:指定“多方”关系时(集合),使用< collection ofType="" >

补充:
省略get.set

public class Department {private Integer id;private String name;private String location;// 存储部门中所有员工信息,注意:返回多个数值,要用list集合接收返回值private List<Employee> employees;
public class Employee {private Integer id;private String name;private Double salary;// 员工从属的部门信息private Department department;
public interface DepartmentDAO {// 查询部门,及其所有员工信息Department queryDepartmentById(@Param("id") Integer id);
}
public interface EmployeeDAO {// 查询员工信息 并且 查到对应的部门信息Employee queryEmployeeById(@Param("id") Integer id);
}
<?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.qf.dao.DepartmentDAO"><resultMap id="dept_emp" type="Department"><id column="id" property="id"></id><result column="name" property="name"></result><result column="location" property="location"></result><!-- emp_id  emp_name  salary    employees --><collection property="employees" ofType="Employee"><id column="emp_id" property="id"></id><result column="emp_name" property="name"></result><result column="salary" property="salary"></result></collection></resultMap><select id="queryDepartmentById" resultMap="dept_emp">select t_departments.id ,t_departments.name,t_departments.location,t_employees.id emp_id,t_employees.name emp_name,t_employees.salaryfrom t_departments join t_employeeson t_departments.id = t_employees.dept_idwhere t_departments.id=#{id}</select></mapper>
<?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.qf.dao.EmployeeDAO"><resultMap id="emp_dept" type="Employee"><id column="id" property="id"></id><result column="name" property="name"></result><result column="salary" property="salary"></result><association property="department" javaType="Department"><id column="deptId" property="id"></id><result column="deptName" property="name"></result><result column="location" property="location"></result></association></resultMap><select id="queryEmployeeById" resultMap="emp_dept">select t_employees.id,t_employees.name,t_employees.salary,t_departments.id deptId ,t_departments.name deptName,t_departments.locationfrom t_employees join t_departmentson t_departments.id = t_employees.dept_idwhere t_employees.id=#{id}</select></mapper>

测试

        DepartmentDAO departmentDAO = MyBatisUtil.getMapper(DepartmentDAO.class);Department department = departmentDAO.queryDepartmentById(1);System.out.println(department);//返回的员工为多个,放到list<>集合中,所以需要增强for循环遍历。List<Employee> employees = department.getEmployees();for (Employee employee : employees){System.out.println(employee);}

测试的时候检查Mapper是否没在配置文件中注册。
如果还是不行就是要maven-clear一下


一对一使用association标签

        EmployeeDAO mapper = MyBatisUtil.getMapper(EmployeeDAO.class);Employee employee = mapper.queryEmployeeById(2);System.out.println(employee);System.out.println(employee.getDepartment());

10.3 ManyToMany

SQL参考

建立第三张关系表
<mapper namespace="com.qf.mybatis.part2.many2many.StudentDao"><!-- 映射查询只封装两表中的信息,可忽略关系表内容 --><resultMap id="allMap" type="com.qf.mybatis.part2.many2many.Student"><id property="id" column="id" /><result property="name" column="name" /><result property="sex" column="sex" /><collection property="subjects" ofType="com.qf.mybatis.part2.many2many.Subject"><id property="id" column="sid" /><result property="name" column="sname" /><result property="grade" column="grade" /></collection></resultMap><!-- 三表连接查询 --><select id="selectAllStudents" resultMap="allMap">SELECT s1.* , ss.* , s2.id as sid , s2.name as sname , s2.gradeFROM t_students s1 LEFT JOIN t_stu_sub ssON s1.id = ss.student_id <!-- 通过t_stu_sub表建立二者之间的关系 -->LEFT JOIN t_subjects s2ON ss.subject_id = s2.id</select>
</mapper>
  • 注意:指定“多方”关系时(集合),使用< collection ofType="" >

10.4 关系总结

一方,添加集合;多方,添加对象。

双方均可建立关系属性,建立关系属性后,对应的Mapper文件中需使用< ResultMap >完成多表映射。

持有对象关系属性,使用< association property=“dept” javaType=“department” >

持有集合关系属性,使用< collection property=“emps” ofType=“employee” >

MyBatis学习02相关推荐

  1. mybatis学习10

    Mybatis允许在己映射语句执行过程中的某一点进行拦截调用.MyBatis 允许使用插件来拦截的接口和方法包括以下几个: 接口或方法 描述 Executor ( update. query. flu ...

  2. 【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    [转]MyBatis学习总结(四)--解决字段名与实体类属性名不相同的冲突 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体 ...

  3. 事务中mybatis通过id查不到但是通过其他条件可以查到_40打卡 MyBatis 学习

    第57次(mybatis) 学习主题:mybatis 学习目标: 1 掌握框架的概念 2 掌握mybatis环境搭建 对应视频: http://www.itbaizhan.cn/course/id/8 ...

  4. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

  5. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作

    上一篇博文MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对u ...

  6. mybatis学习笔记(7)-输出映射

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(7)-输出映射 标签: mybatis [TOC] 本文主要讲解mybatis的输出映射. 输出映射有 ...

  7. MyBatis学习--简单的增删改查

    jdbc程序 在学习MyBatis的时候先简单了解下JDBC编程的方式,我们以一个简单的查询为例,使用JDBC编程,如下: 1 Public static void main(String[] arg ...

  8. mybatis学习笔记(3)-入门程序一

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(3)-入门程序一 标签: mybatis [TOC] 工程结构 在IDEA中新建了一个普通的java项 ...

  9. Mybatis学习总结二

    Mybatis学习总结二 0.不需要修改的文件(在src下面) jdbc.properties文件 log4j.properties文件 SqlMapConfig.xml文件 1.高级结果映射 1.1 ...

最新文章

  1. CCF系列之画图(201409-2)
  2. 深度学习在计算机视觉领域(包括图像,视频,3-D点云,深度图)的应用一览
  3. 是不是“异常”让我的脑子糊涂了?
  4. 1.第一个java程序,Hello world
  5. Lambda 表达式有何用处?
  6. 【caffe解读】 caffe从数学公式到代码实现2-基础函数类
  7. hibernate07--关联映射
  8. maven安装及集成myeclipse
  9. Linux下高速缓存DNS的配置
  10. bzoj 1681: [Usaco2005 Mar]Checking an Alibi 不在场的证明(BFS)
  11. 洛谷P4548 [CTSC2006]歌唱王国(概率生成函数)
  12. python导入dat数据_收好Python代码,导入项目数据不费力
  13. 目标跟踪之ADMM求解简介
  14. 【windows环境 PKCS11库Demo 用于劫持PKCS11库并打印参数】
  15. LeetCode - 加一
  16. re_mysql_20221210
  17. 【Redis-09】面试题之Redis数据结构与对象-RedisObject(下篇)
  18. 神策发布丨企业微信数字化营销解决方案!
  19. 中国移动CMnet和CMwap两种网络的区别?
  20. 为什么你总是被骗呢?

热门文章

  1. java网络爬虫基础学习(二)
  2. shutdown函数
  3. 计算机网络体系结构整理-第九单元移动IP
  4. SpringCloud观后感
  5. explain和profiling分析查询SQL时间
  6. .NET单元测试-多线程
  7. Beta冲刺 day4
  8. Oracle HA 之 SERVICE和DRM实战
  9. asp.net引入一个js文件名为JScript的js脚本 报错 缺少对象
  10. silverlight 3 blend3最新版本 破解方法