Mybatis配置文件


MyBatis映射文件

Editor:SimpleWu

MyBatis真正的核心是在映射文件,由於它的異常強大,如果拿它和相同功能的JDBC代碼相比,你會發現它省掉了將近95%的代碼。

MyBatis實體類映射文件

MyBatis有一下幾個頂級元素

select:映射查詢語句

<select id="findAll" resultType="com.simple.mybatis.entitys.Employee">
		select * from tal_employee
</select>

insert:映射插入語句

使用#{參數屬性名}賦值

<insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

update:映射修改語句

<update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
		update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
</update>

delete:映射刪除語句

<delete id="deleteEmp" parameterType="Integer">
		delete from tal_employee where id=#{id}
</delete>

sql:可以被其它sql語句重用的sql語句。
resultMap:是最復雜也是最強大的元素,用來和數據庫表和實體類進行映射。

<resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
	<id property="id" column="id"/>
	<result property="lastName" column="last_name"/>
	<result property="email" column="email"/>
	<result property="gender" column="gender"/>
</resultMap>

<!-- 返回外部resultMap格式的類型。-->
<select id="findAll" resultMap="Employee">
	select id,last_name AS lastName,email,gender from tal_employee
</select>

cache:給定命名空間的緩存配置。
cache-ref:其它命名空間緩存配置的引用。

我們結合第一章,使用之前與數據庫互交的方式:

sqlSession.selectList("命名空間.select標簽ID");
sqlSession.selectOne("命名空間.select標簽ID");
sqlSession.update("命名空間.update標簽ID", "Object類型參數");
sqlSession.delete("命名空間.delete標簽ID", "Object類型參數");
sqlSession.insert("命名空間.insert標簽ID", "Object類型參數");

增刪改必須提交事務:sqlSession.commit();

使用XML映射文件方式來在執行方法時,由於是通過字符串方式來調用方法,對類型的約束也不是強制性的,可讀性較差,這是早期ibatis的調用方式。除此之外Mybatis還提供另外兩種實現方式

MyBatis注解方式

  1. @Select:用來修飾使用查詢語句的方法

  2. @Insert:用來修飾使用增加語句的方法、

  3. @Update:用來修飾使用修改修改的方法。

  4. @Delete:用來修飾使用刪除語句的方法。

    public interface EmployeeAnnotation {
    @Select("select id,last_name AS lastName,email,gender from tal_employee")
    List findAll();

     @Insert("insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})")
     int saveEmp(Employee employee);
     
     @Update("update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}")
     boolean updateEmp(Employee employee);
     
     @Delete("elete from tal_employee where id=#{id}")
     long deleteEmp(Integer id);
    

    }

然后我們需要在mybatis主配置文件中映射這個注解接口

<!-- 映射注解類 -->
<mapper class="com.simple.mybatis.dao.EmployeeAnnotation"/>

@Test
	public void testAnnotation(){
		SqlSession session = sqlSessionFactory.openSession();
		EmployeeAnnotation employeeAnnotation = session.getMapper(EmployeeAnnotation.class);
		Employee employee = new Employee("測試注解增加", "email", "男");
		employeeAnnotation.saveEmp(employee);
		//提交事務
		session.commit();
		session.close();
}

使用注解雖然更加方便,但是配置復雜sql語句時較為復雜。所以很多時候采用兩種相結合的方式。

Mybatis接口編程

我們首先添加一個接口

public interface EmployeeMapper {
	List<Employee> findAll();
	
	int saveEmp(Employee employee);
	
	boolean updateEmp(Employee employee);
	
	long deleteEmp(Integer id);
}

實體類映射文件命名空間(namespace)必須對應接口全名,並且里面的方法需要對應里面增刪改查標簽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.simple.mybatis.dao.EmployeeMapper">
	<resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
		<id property="id" column="id"/>
		<result property="lastName" column="last_name"/>
		<result property="email" column="email"/>
		<result property="gender" column="gender"/>
	</resultMap>

	<!-- 返回外部resultMap格式的類型。-->
	<select id="findAll" resultMap="Employee">
		select id,last_name AS lastName,email,gender from tal_employee
	</select>
	
	<insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
	</insert>
	
	<update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
		update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
	</update>
	
	<delete id="deleteEmp" parameterType="Integer">
		delete from tal_employee where id=#{id}
	</delete>
</mapper>

並且必須在MyBatis主配置文件中加載這個映射文件

<mappers>
		<mapper resource="com/simple/mybatis/entitys/EmployeeMapper.xml" />
</mappers>

使用方式:

@Test
	public void test4(){
		SqlSession session = sqlSessionFactory.openSession();
		//獲取接口。這個接口mybatis會幫我創建代理實現類完成接口與XML映射的綁定
		EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
		employeeMapper.deleteEmp(1);
		session.commit();
		session.close();
	}

獲取插入后的自動增長主鍵

useGeneratedKeys參數只針對 insert 語句生效,默認為 false。當設置為 true 時,表示如果插入的表以自增列為主鍵,則允許 JDBC 支持自動生成主鍵,並可將自動生成的主鍵返回。 keyProperty是要封裝給parameterType="com.simple.mybatis.entitys.Employee中的主鍵ID屬性名

<insert id="saveEmpGetKey" parameterType="com.simple.mybatis.entitys.Employee"
	useGeneratedKeys="true" keyProperty="id"
	>
		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

@Test
	public void saveEmpGetKey(){
		SqlSession session = sqlSessionFactory.openSession();
		EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
		Employee employee = new Employee("自動封裝主鍵", "email", "男");//增加之前主鍵沒賦值
		employeeMapper.saveEmpGetKey(employee);
		session.commit();//提交事務
		System.out.println("增加后主鍵有值: " + employee.getId());
		session.close();//關閉資源
	}

Mybatis參數規則

一個參數時:

直接使用#{xxx}來訪問參數即可。參數名稱任意。例如#{a},#{b}都可以訪問參數值。如果是集合(Collection,List,Set)類型,使用集合名稱小寫作為key值。

必須接口方法:

long deleteEmp(Integer emp);

映射文件:

<delete id="deleteEmp" parameterType="Integer">
		delete from tal_employee where id=#{id}
</delete>

在這里可以看到我們是沒有給這個賦值的,#{id}我這個屬性名也不叫id而是emp。所以一個參數是名字可以任意如果是傳入的集合類型

傳入Map參數時取值:

//接口有方法:long deleteEmp(Map<String, Object> map);
<delete id="deleteEmp" parameterType="Map">
		delete from tal_employee where id=#{empID}
</delete>

我們這里取值是empID,這想想都知道創建一個map.put(“empID”,1)作為參數傳入方法調用就行了

多個參數時:

  1. 默認:就不能使用#{xxx}來訪問參數了。當有多個參數時,mybatis會將參數封裝為一個map集合,只能通過#{下標}或者#{paramN}的方式來獲取值。
  2. 命名參數:明確指定封裝參數時手動指定map的key。通過在接口方法上添加@Param("key")來指定參數名稱。
  3. 實體類:如果多個參數是封裝好的業務類,那么直接傳入業務對象即可。可以通過#{屬性名}獲取屬性即可。Map:如果多個參數不是已封裝的業務類,那么傳入map集合即可。通過#{key}獲取對應的value值。

{}和${}

MyBatis中,除了可以使用#{}來獲取參數的值意外,還可以使用${}來獲取參數的值。

區別:#{}:會以預編譯的方式,將參數生成到sql語句中。${}:會直接將值生成到sql語句。

大多數情況下,我們都是以#{}來獲取參數,但是有些地方不支持占位符的地方那么就可以使用${}來獲取參數,比如表名。

resultType返回類型

  1. 對於增刪改的方法,Mybatis會自動對結果進行封裝,返回int,Boolean,long都可以。
  2. 對於返回實體對象和List集合,resultType可以設置為實體類型。
  3. 如果返回單個對象,也可以封裝為Map<String,Object>,resultType設置為map。
  4. 如果返回Map集合對象,比如Map<String,Student>,resultType設置為Student類型,通過@MapKey("id")注解來修飾放入Map中的key值。

ResultMap標簽介紹

ResultMap的常用子標簽

  1. id:映射主鍵。result:映射普通列。
  2. association:復雜結果映射。
  3. collection:復雜類型的集合映射。
  4. constructor:構造函數注入。

前面我們的案例我們數據庫的字段與實體類的屬性基本上一致,或者不一致使用取別名方案解決,可是每條語句都去取別名是非常麻煩的,ResultMap這個標簽就很好的解決數據庫與實體類字段不對應的問題

我們新創建一個部門表:

CREATE TABLE tal_dept(
	d_id INT PRIMARY KEY AUTO_INCREMENT,
	d_name VARCHAR(50)
);

對應實體類:

public class Dept {
	private Integer id;
	private Integer name;
}

如果我們查詢語句直接使用resultType="com.simple.mybatis.entitys.Dept那么毫無疑問我們的實體類中名字不對應是賦值為null的,我們可以ResultMap映射實體類與數據庫的對應關系

<!--配置返回結果,配置數據庫字段與類屬性的映射-->
<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
		<id column="d_id" property="id"/>
		<result column="d_name" property="name"/>
</resultMap>
<!--使用resultMap使用指向上面返回結果的ID-->
<select id="getDeptOne" parameterType="Integer" resultMap="DeptResult">
		select * from tal_dept where d_id = #{id}
</select>

關系映射

在數據庫中,許多數據是分布在多個表中的,有時候需要將多個表的數據關聯起來進行查詢。那么在ORM框架中,我們需要處理數據表的映射關系。

常見的映射關系:

  1. 關聯屬性映射association
  2. 映射collection映射

result方式映射屬性

這種方式並不推薦,沒有什么重用性

<resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
		<id property="id" column="id"/>
		<result property="lastName" column="last_name"/>
		<result property="email" column="email"/>
		<result property="gender" column="gender"/>
		<!-- 指定Employee中Dept對象屬性 -->
		<result property="dept.id" column="d_id"/>
		<result property="dept.name" column="d_name"/>
</resultMap>
<select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
		select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
</select>

association映射(分步查詢)

多對一,查詢員工獲取員工中的部門:

<resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
		<id property="id" column="id"/>
		<result property="lastName" column="last_name"/>
		<result property="email" column="email"/>
		<result property="gender" column="gender"/>
		<!-- property指定實體類中對象dept 指定發過去的參數column="d_id" 
			 select指定com.simple.mybatis.dao.DeptMapper映射文件中getDeptOne查詢方法
		 -->
		<association property="dept" column="d_id" 
		select="com.simple.mybatis.dao.DeptMapper.getDeptOne"></association>
</resultMap>
<!--resultMap指定使用上面定義的返回結果-->
<select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
		select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
</select>

Collection查詢

一對多,獲取部門同時部門中員工也獲取:

<!--部門映射-->
<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
		<id column="d_id" property="id"/>
		<result column="d_name" property="name"/>
    	<!--property指定Dept中集合屬性名 ofType指定集合中屬性類型 -->
		<collection property="Employees" ofType="com.simple.mybatis.entitys.Employee" >
			<id property="id" column="id"/>
			<result property="lastName" column="last_name"/>
			<result property="email" column="email"/>
			<result property="gender" column="gender"/>
		</collection>
</resultMap>
<select id="getDeptAll" resultMap="DeptResult">
		select * from tal_dept d left join tal_Employee e on d.d_id = e.d_id
</select>

Collection嵌套查詢

一對多分布查詢

<resultMap type="com.simple.mybatis.entitys.Dept" id="DeptOrEmployee">
		<id column="d_id" property="id"/>
		<result column="d_name" property="name"/>
    	<!--select指定com.simple.mybatis.dao.EmployeeMapper映射文件中的getEmployeeByDeptId-->
		<collection property="Employees" column="d_id" 	ofType="com.simple.mybatis.entitys.Employee" 
		select="com.simple.mybatis.dao.EmployeeMapper.getEmployeeByDeptId">
		</collection>
	</resultMap>
<!--com.simple.mybatis.dao.EmployeeMapperXML中方法-->
<select id="getEmployeeByDeptId" parameterType="Integer" resultType="com.simple.mybatis.entitys.Employee">
		select * from tal_employee where d_id = #{id}
	</select>

關聯查詢和分步查詢的區別:

  1. 關聯查詢一次將多個表的數據查詢出來,分步查詢通過多次查詢獲取查詢結果。
  2. 配置文件不同,關聯查詢需要定義額外的映射,分步查詢需要定義外鍵列,和查詢的select方法。
  3. 關聯查詢不支持延遲加載,分步查詢支持延遲加載。fetchType="lazy"

延遲加載

剛才分布查詢是一次將結果查詢出來,為了提高效率,mybatis還支持延遲加載技術,等需要用到對象時才進行查詢。

在mybatis主配置文件中配置:

<!– 通過全局配置文件設置延遲加載-->
<settings>
<!-- 全局啟用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 當啟用時,有延遲加載屬性的對象在被調用時將會完全加載任意屬性。否則,每種屬性將會按需要加載。 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

設置級聯延遲加載

<!– 設置延遲加載屬性-->
<association fetchType="lazy"/>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM