MyBatis映射文件sql
Editor:SimpleWu數據庫
MyBatis真正的核心是在映射文件,因爲它的異常強大,若是拿它和相同功能的JDBC代碼相比,你會發現它省掉了將近95%的代碼。編程
MyBatis實體類映射文件緩存
MyBatis有一下幾個頂級元素session
select:映射查詢語句mybatis
<select id="findAll" resultType="com.simple.mybatis.entitys.Employee"> select * from tal_employee </select>
insert:映射插入語句app
使用#{參數屬性名}賦值框架
<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註解方式
@Delete:用來修飾使用刪除語句的方法。
public interface EmployeeAnnotation {
@Select("select id,last_name AS lastName,email,gender from tal_employee")
List
@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)做爲參數傳入方法調用就好了
多個參數時:
MyBatis中,除了可使用#{}來獲取參數的值意外,還可使用${}來獲取參數的值。
區別:#{}:會以預編譯的方式,將參數生成到sql語句中。${}:會直接將值生成到sql語句。
大多數狀況下,咱們都是以#{}來獲取參數,可是有些地方不支持佔位符的地方那麼就可使用${}來獲取參數,好比表名。
resultType返回類型
ResultMap標籤介紹
ResultMap的經常使用子標籤
前面咱們的案例咱們數據庫的字段與實體類的屬性基本上一致,或者不一導致用取別名方案解決,但是每條語句都去取別名是很是麻煩的,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框架中,咱們須要處理數據表的映射關係。
常見的映射關係:
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>
關聯查詢和分步查詢的區別:
延遲加載
剛纔分佈查詢是一次將結果查詢出來,爲了提升效率,mybatis還支持延遲加載技術,等須要用到對象時才進行查詢。
在mybatis主配置文件中配置:
<!– 經過全局配置文件設置延遲加載--> <settings> <!-- 全局啓用或禁用延遲加載。當禁用時,全部關聯對象都會即時加載。 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 當啓用時,有延遲加載屬性的對象在被調用時將會徹底加載任意屬性。不然,每種屬性將會按須要加載。 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
設置級聯延遲加載
<!– 設置延遲加載屬性--> <association fetchType="lazy"/>