MyBatis學習02

 2023-11-30 阅读 30 评论 0

摘要:八、MyBatis工具類【重點】 8.1 封裝工具類 Resource:用于獲得讀取配置文件的IO對象,耗費資源,建議通過IO一次性讀取所有所需要的數據。 SqlSessionFactory:SqlSession工廠類,內存占用多,耗費資源,建議每個應用只創建一個對

八、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” >

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/186152.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息