重點
】MyBatis的映射文件中支持在基礎SQL上添加一些邏輯操作,并動態拼接成完整的SQL之后再執行,以達到SQL復用、簡化編程的效果。
<mapper namespace="com.qf.mybatis.part2.dynamic.BookDao"><sql id="BOOKS_FIELD"> <!-- 定義SQL片段 -->SELECT id,name,author,publish,sort</sql><select id="selectBookByCondition" resultType="com.qf.mybatis.part2.dynamic.Book"><include refid="BOOKS_FIELD" /> <!-- 通過ID引用SQL片段 -->FROM t_books</select>
</mapper>
補充:
<!-- 抽取重復sql片段 --><sql id="user_field">select id,username,password,gender,regist_time registTimefrom t_user </sql><select id="queryUsers" resultType="User"><!-- 引用sql片段 --><include refid="user_field"/></select>
查詢是很頻繁的,如果查詢的列特別多,那就需要再DAO中寫特別多的方法,現在可以創建一個
Mybatis框架,User queryUser (User user);
方法,可以把User的屬性全部返回出來,我們可以在mapper.xml對方法的描述時做 if 判斷,想要誰那就返回誰。
那就只需要寫一個方法即可
<?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.UserDAO"><!-- 抽取重復sql片段 --><sql id="user_field">select id,username,password,gender,regist_time registTimefrom t_user</sql><select id="queryUsers" resultType="User"><!-- 引用sql片段 --><include refid="user_field"/></select><select id="queryUser" resultType="User"><include refid="user_field"/>where<if test="id != null">id=#{id}</if><if test="username != null">username=#{username}</if></select></mapper>
補充:
@before注解
UserDAO mapper;@Before//@before注解是junit的注解,可以在下面方法執行前都執行被修飾的方法,把通用語句放進去//此處就是每次都創建一個mapper,public void init(){mapper= MyBatisUtil.getMapper(UserDAO.class);}
java_home environment variable?如果查詢多個條件是,會涉及or和and,但是前后如果有條件 if 不滿足會造成SQL語句錯誤。那就要使用where標簽,把內容包裹起來。
<!-- where標簽:1. 補充where關鍵字2. 識別where子句中如果 以or,and開頭,會將or,and去除--><where><if test="username!=null">username=#{username}</if><if test="gender!=null">and gender=#{gender}</if></where>
實際更新可能只需要改某一個字段
接受一個對象,如果某個字段為空那就不需要更新。
按照之前的if標簽可進行選擇,如果修改全部字段沒問題,但是其中一個字段為null的話,if標簽里面的SQL語句后面會存在一個逗號,引起SQL語法報錯。
<update id="updateuser">UPDATE tables<!--1. 補充set2. 自動將set子句的最后的逗號去除--><!--<set><if test="username!=null">username=#{username},</if><if test="password!=null">password=#{password},</if><if test="gender!=null">gender=#{gender},</if><if test="registTime!=null">regist_time=#{registTime}</if></set>-->WHERE id = #{id}
</update>
< trim prefix="" suffix="" prefixOverrides="" suffixOverrides="" >代替< where > 、< set >
java groupingby。prefix加前綴 suffix加后綴
trim是一個比較綜合的標簽,可以實現where和set的功能
<!-- prefix="where" 補充where關鍵字prefixOverrides="or|and" where子句中如果以or或and開頭,會被干掉--><trim prefix="where" prefixOverrides="or|and"><if test="username!=null">username=#{username}</if><if test="gender!=null">and gender=#{gender}</if></trim>
<update id="方法名">UPDATE table<!-- prefix="set" 補充一個setsuffixOverrides="," 自動將set子句的最后的逗號去除--><trim prefix="set" suffixOverrides=","><if test="username!=null">username=#{username},</if><if test="password!=null">password=#{password},</if><if test="gender!=null">gender=#{gender},</if><if test="registTime!=null">regist_time=#{registTime}</if></trim>WHERE id = #{id}
</update>
<delete id="deleteByIds">DELETE FROM t_booksWHERE id IN<foreach collection="list" open="(" separator="," close=")" item="id" index="i">#{id}</foreach>
</delete>
參數 | 描述 | 取值 |
---|---|---|
collection | 容器類型 | list、array、map |
open | 起始符 | ( |
close | 結束符 | ) |
separator | 分隔符 | , |
index | 下標號 | 從0開始,依次遞增 |
item | 當前項 | 任意名稱(循環中通過 #{任意名稱} 表達式訪問) |
補充:
public interface UserDAO {List<User> queryUsers();/*User queryUserById(@Param("id") Integer id);User queryUserByUsername(@Param("username") String username);*/User queryUser(User user);List<User> queryUser2(User user);Integer deleteUser(@Param("id") Integer id);Integer updateUser(User user);Integer insertUser(User user);Integer deleteManyUser(List<Integer> ids);Integer insertManyUser(List<User> users);
}
<!--foreach描述in()括號中的內容,注意輸入類型是list<>集合--><delete id="deleteManyUser" parameterType="java.util.List"><!--delete from t_user where id in (x,x,x,x,x,x)-->delete from t_user where id in<foreach collection="list" open="(" close=")" item="id9" separator=",">#{id9}</foreach></delete>
foreach描述:遍歷一個list集合,以(開頭,以)結尾,每次輸出結果存到id9的結果上,然后把id9作輸出,中間以逗號分隔。
同理可以使用foreach作添加操作
<insert id="insertManyUser" parameterType="java.util.List"><!--insert into t_user (null,x,x,x,x,x,x),(null,xxxx,xxx,xx)-->insert into t_user values<!--foreach描述:insertManyUser方法返回為list,遍歷是list--><foreach collection="list" close="" open="" item="user9" separator=",">(null,#{user9.username},#{user9.password},#{user9.gender},#{user9.registTime})</foreach></insert>
@Testpublic void test5(){List<Integer> ids = Arrays.asList(10006, 10007, 10008, 10009);mapper.deleteManyUser(ids);MyBatisUtil.commit();//修改數據,需要對事務進行提交}//Arrays.asList() 該方法是將數組轉化成List集合的方法。@Testpublic void test6(){List<User> users = Arrays.asList(new User(null, "張三", "123", true, new Date()),new User(null, "李四", "456", false, new Date()));mapper.insertManyUser(users);MyBatisUtil.commit();}
重點
】內存中的一塊存儲空間,服務于某個應用程序,旨在將頻繁讀取的數據臨時保存在內存中,便于二次快速訪問。
存在內存中的數據是頻繁被訪問,但是很少被更新的數據。
無緩存:用戶在訪問相同數據時,需要發起多次對數據庫的直接訪問,導致產生大量IO、讀寫硬盤的操作,效率低下 |
---|
|
有緩存:首次訪問時,查詢數據庫,將數據存儲到緩存中;再次訪問時,直接訪問緩存,減少IO、硬盤讀寫次數、提高效率 |
---|
SqlSession級別的緩存,同一個SqlSession的發起多次同構查詢,會將數據保存在一級緩存中。
@Testpublic void test7(){SqlSession sqlSession = MyBatisUtil.openSession();UserDAO mapper = sqlSession.getMapper(UserDAO.class);List<User> users = mapper.queryUsers();System.out.println("===========");List<User> users1 = mapper.queryUsers();//再查一次//查詢結果發現只查詢了一次,所以一級緩存默認開啟System.out.println("-------------------------------");SqlSession session = MyBatisUtil.getSession();//mybatisUtil添加getSession方法,獲取新的session//getsession方法直接返回sqlsession,不再綁定唯一UserDAO mapper1 = session.getMapper(UserDAO.class);mapper1.queryUsers();}
小結:
SqlSessionFactory級別的緩存,同一個SqlSessionFactory構建的SqlSession發起的多次同構查詢,會將數據保存在二級緩存中。
< settings >是MyBatis中極為重要的調整設置,他們會改變MyBatis的運行行為,其他詳細配置可參考官方文檔。
放到mybatis-config.xml
<configuration><properties .../><!-- 注意書寫位置 --><settings><setting name="cacheEnabled" value="true"/> <!-- mybaits-config.xml中開啟全局緩存(默認開啟) --></settings><typeAliases></typeAliases>
</configuration>
注意:mybatis的配置文件的標簽有明確的順序,可以查看 configuration 標簽
<!--(properties?, settings?, typeAliases?,typeHandlers?, objectFactory?, objectWrapperFactory?,reflectorFactory?, plugins?, environments?,databaseIdProvider?, mappers?)-->
在mapper文件中加上<cache / >標簽,開啟二極緩存
<mapper namespace="com.qf.mybatis.part2.cache.BookDao"><!-- 二級緩存默認開啟的,但并不是所有的查詢結果,都會進入二級緩存 --><cache/><select id="selectBookByCondition" resultType="com.qf.mybatis.part2.cache.Book">SELECT * FROM t_books</select>
</mapper>
@Test
public void testMapperCache(){SqlSession sqlSession1 = MyBatisUtils.getSession();BookDao bookDao1 = sqlSession1.getMapper(BookDao.class);bookDao1.selectBookByCondition(new Book());sqlSession1.close(); //必須關閉SqlSession才可緩存數據//--------------------SqlSession sqlSession2 = MyBatisUtils.getSession();BookDao bookDao2 = sqlSession2.getMapper(BookDao.class);bookDao2.selectBookByCondition(new Book());sqlSession2.close(); //緩存擊中
}
小結:
如果數據庫中數據被增刪改之后就需要清除緩存
@Test
public void testMapperCache(){SqlSession sqlSession1 = MyBatisUtils.getSession();BookDao bookDao1 = sqlSession1.getMapper(BookDao.class);bookDao1.selectBookByCondition(new Book());sqlSession1.close(); //必須關閉SqlSession才可緩存數據//--------------------SqlSession sqlSession3 = MyBatisUtils.getSession();BookDao bookDao3 = sqlSession3.getMapper(BookDao.class);bookDao3.deleteBookById(102);sqlSession3.commit(); //DML成功,數據發生變化,緩存清空sqlSession3.close();//--------------------SqlSession sqlSession2 = MyBatisUtils.getSession();BookDao bookDao2 = sqlSession2.getMapper(BookDao.class);bookDao2.selectBookByCondition(new Book());sqlSession2.close(); //緩存未擊中,重新查詢數據庫、重新緩存
}
使用同一個mapper刪除就會被移除。
第一次查詢,數據緩存到內存中,第二次刪除,數據被刪除持久化。第三次重新查詢,緩存未被擊中。
之前做的每一個請求都需要一個連接,整個流程是比較費時間的,并且消耗資源。
Druid 是阿里巴巴開源平臺上的一個項目,整個項目由數據庫連接池、插件框架和 SQL 解析器組成。該項目主要是為了擴展 JDBC 的一些限制,可以讓程序員實現一些特殊的需求,比如向密鑰服務請求憑證、統計 SQL 信息、SQL 性能收集、SQL 注入檢查、SQL 翻譯等,程序員可以通過定制來實現自己需要的功能。
測試執行申請歸還連接 1,000,000(一百萬)次總耗時性能對比。
環境 | 版本 |
---|---|
OS | OS X 10.8.2 |
CPU | Intel i7 2GHz 4 Core |
JVM | Java Version 1.7.0_05 |
JDBC-Conn Pool | 1 Thread | 2 threads | 5 threads | 10 threads | 20 threads | 50 threads |
---|---|---|---|---|---|---|
Druid | 898 | 1,191 | 1,324 | 1,362 | 1,325 | 1,459 |
tomcat-jdbc | 1,269 | 1,378 | 2,029 | 2,103 | 1,879 | 2,025 |
DBCP | 2,324 | 5,055 | 5,446 | 5,471 | 5,524 | 5,415 |
BoneCP | 3,738 | 3,150 | 3,194 | 5,681 | 11,018 | 23,125 |
jboss-datasource | 4,377 | 2,988 | 3,680 | 3,980 | 32,708 | 37,742 |
C3P0 | 10,841 | 13,637 | 10,682 | 11,055 | 14,497 | 20,351 |
Proxool | 16,337 | 16,187 | 18,310(Ex) | 25,945 | 33,706(Ex) | 39,501 (Ex) |
引入Druid依賴
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version>
</dependency>
MyDruidDataSourceFactory并繼承PooledDataSourceFactory,并替換數據源。
package com.qf.mybatis.part2.utils;import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasou rce.pooled.PooledDataSourceFactory;public class MyDruidDataSourceFactory extends PooledDataSourceFactory {public MyDruidDataSourceFactory() {this.dataSource = new DruidDataSource();//替換數據源}
}
//會返回德魯伊連接池的一個對象。
mybatis-config.xml中連接池相關配置。
<!--連接池--><!-- 數據連接參數 --><dataSource type="com.qf.datasource.MyDruidDataSourceFactory"><property name="driverClass" value="${jdbc.driver}"/><!-- &轉義& --><property name="jdbcUrl" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource>
注意:< property name=“屬性名” />屬性名必須與com.alibaba.druid.pool.DruidAbstractDataSource中一致。
PageHelper是適用于MyBatis框架的一個分頁插件,使用方式極為便捷,支持任何復雜的單表、多表分頁查詢操作。
官方網站:https://pagehelper.github.io/
下載地址:https://github.com/pagehelper/Mybatis-PageHelper
PageHelper中提供了多個分頁操作的靜態方法入口。
pom.xml中引入PageHelper依賴。
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.10</version>
</dependency>
在MyBatis-config.xml中添加< plugins >。
<configuration><typeAliases></typeAliases><plugins><!-- com.github.pagehelper為PageHelper類所在包名 --><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins><environments>...</environments>
</configuration>
使用PageHelper提供的靜態方法設置分頁查詢條件。
@Testpublic void testPage(){UserDAO mapper = MyBatisUtil.getMapper(UserDAO.class);//在查詢前,設置分頁 查詢第一頁,每頁2條數據// PageHelper特點: 對其之后的第一個查詢,進行分頁功能追加PageHelper.startPage(1,2);List<User> users = mapper.queryUsers();for (User user : users) {System.out.println(user);}// 將查詢結果 封裝到 PageInfo對象中PageInfo<User> pageInfo = new PageInfo(users);System.out.println("================");}
PageInfo對象中包含了分頁操作中的所有相關數據。
PageInfo結構圖 |
---|
使用PageInfo保存分頁查詢結果。
@Test
public void testPageInfo(){UserDao userDao = MyBatisUtils.getMapper(UserDao.class);PageHelper.startPage(6, 2);List<User> users = userDao.selectAllUsers();PageInfo<User> pageInfo = new PageInfo<User>(users);//將分頁查詢的結果集保存在PageInfo對象中System.out.println(pageInfo);
}
- 只有在PageHelper.startPage()方法之后的第一個查詢會有執行分頁。
- 分頁插件不支持帶有“for update”的查詢語句。
- 分頁插件不支持“嵌套查詢”,由于嵌套結果方式會導致結果集被折疊,所以無法保證分頁結果數量正確。。
使用Servlet+JSP+MyBatis+分頁插件,完成分頁查詢功能。
以下內容并非必備知識,了解即可。
通過在接口中直接添加MyBatis注解,完成CRUD。
<mappers><mapper class="com.qf.mybatis.part1.annotations.UserMapper" /><!-- class="接口全限定名"-->
</mappers>
public interface UserMapper {@Select("SELECT * FROM t_users WHERE id = #{id}")public User selectUserById(Integer id);@Select("SELECT * FROM t_users WHERE id = #{id} AND password = #{pwd}")public User selectUserByIdAndPwd_annotation(@Param("id") Integer id, @Param("pwd") String password);
}
@Delete(value = "DELETE FROM t_users WHERE id = #{id}")
public int deleteUser(Integer id);
@Update("UPDATE t_users SET name = #{name} , password = #{password} , salary = #{salary} , birthday = #{birthday} WHERE id = #{id}")
public int updateUser(User user);
@Insert("INSERT INTO t_users VALUES(#{id},#{name},#{password},#{salary},#{birthday},null)")
public int insertUser(User user);@Options(useGeneratedKeys = true , keyProperty = "id") // 自增key,主鍵為id
@Insert("INSERT INTO t_users VALUES(#{id},#{name},#{password},#{salary},#{birthday},null)")
public int insertUserGeneratedKeys(User user);
補充:UserDAO接口
@Select("SELECT id,username,password,gender,regist_time FROM t_user")List<User> queryUsers();@Select("SELECT id,username,password,gender,regist_time\n" +" FROM t_user\n" +" WHERE id = #{id}")User queryUserById(@Param("id") Integer id);@Delete("delete from t_user\n" +" where id=#{id}")Integer deleteUser(@Param("id") Integer id);@Update("update t_user\n" +" set username=#{username},password=#{password},gender=#{gender},regist_time=#{registTime}\n" +" where id=#{id}")Integer updateUser(User user);
主鍵回填:
@Options(useGeneratedKeys = true , keyProperty = "id") // 自增key,主鍵為id@Insert("insert into t_user values(#{id},#{username},#{password},#{gender},#{registTime})")Integer insertUser(User user);
Test
@Testpublic void test1(){UserDAO mapper = MyBatisUtil.getMapper(UserDAO.class);List<User> users = mapper.queryUsers();for (User user : users) {System.out.println(user);}System.out.println("============");User user = mapper.queryUserById(10011);System.out.println(user);//mapper.deleteUser(10011);User new_user = new User(null, "new_user", "1111", true, new Date());//mapper.insertUser(new_user);System.out.println("新用戶id:"+new_user.getId());//mapper.updateUser(new User(10015,"張三2","11111",true,new Date()));MyBatisUtil.commit();}
注解開發: 第一步寫DAO,第二步寫注解,第三步注冊到mybatis-config.xml
小結注解:
${attribute} 屬于字符串拼接SQL,而非預編譯占位符,會有注入攻擊問題,不建議在常規SQL中使用,常用于可解決動態生降序問題。
public List<User> selectAllUsers1(User user); // ${name} ${id} 可獲取user中的屬性值
public List<User> selectAllUsers2(@Param("rule") String rule); //必須使用@Param否則會作為屬性解析
<select id="selectAllUsers1" resultType="user">SELECT * FROM t_users WHERE name = '${name}' or id = ${id} <!-- 拼接name和id,如果是字符類型需要用單引號:'${name}' -->
</select>
<select id="selectAllUsers2" resultType="user">SELECT * FROM t_users ORDER BY id ${rule} <!-- 拼接 asc | desc -->
</select>
User user = new User(....);
List<User> ulist1 = userDAO.selectAllUsers1(user); //調用時傳入user對象List<User> ulist2 = userDao.selectAllUsers2("desc"); //調用時傳入asc | desc
<select id="selectUsersByKeyword" resultType="user">SELECT * FROM t_userWHERE name = '${name}' <!-- 會存在注入攻擊 比如傳入參數是 【String name = "tom' or '1'='1";】-->
</select>
注入攻擊,拼接的內容,改變了原sql語義,被攻擊! |
---|
|
$符小結:
缺點:
3. 本質區別:用#號取值,用的是一個占位符,$是直接進行拼接
#號使用占位符
/*** 1.占位符:規避sql注入風險* 2.占位符要和列相關位置才可以使用* 原則:填充數據,要和列相關* select * from t_user where id=?* insert into t_user values(?,?,?)* update t_user set username=?,password=?* @throws ClassNotFoundException* @throws SQLException*/@Testpublic void test2() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_shine?useUnicode=true&characterEncoding=utf-8","root","111111");//要填充的數據String username = "shine_66' or '1'='1";String rule = "desc";String sql = "select * from t_user where username=?";String sql2 = "select * from t_user order by id ?";PreparedStatement preparedStatement = connection.prepareStatement(sql2);// 在占位符上 填充descpreparedStatement.setString(1,rule);ResultSet resultSet = preparedStatement.executeQuery();while(resultSet.next()){System.out.println(resultSet.getInt("id"));System.out.println(resultSet.getString("username"));}}
上述SQL變成select * from t_user order by id=“shine_66’ or ‘1’='1”
數據庫中是找不到這個字符的
$直接拼接
/*** 1. sql注入風險* 2. 隨意拼接* @throws ClassNotFoundException* @throws SQLException*/
@Testpublic void test3() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_shine?useUnicode=true&characterEncoding=utf-8","root","111111");//要填充的數據String username = "shine_xxx' or '1'='1";String rule = "desc";//sq拼接填充數據 select * from t_user where username='shine_66'//sq拼接填充數據 select * from t_user where username='shine_xxx' or '1'='1'// 當拼接sql片段,有sql注入風險,外界參數改變原有sql的語義String sql = "select * from t_user where username='"+username+"'";String sql2 = "select * from t_user order by id "+rule;Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql2);while(resultSet.next()){System.out.println(resultSet.getInt("id"));System.out.println(resultSet.getString("username"));}}
綜上:當拼接sql片段,有sql注入風險,外界參數改變原有sql的語義。原則上能不用拼接就不用。
String rule = "desc";String sql2 = "select * from t_user order by id "+rule;
思路:查詢部門信息時,及聯查詢所屬的員工信息。
- DepartmentDao接口中定義selectDepartmentById,并實現Mapper。
- EmployeeDao接口中定義selectEmployeesByDeptId,并實現Mapper,
- 當selectDepartmentById被執行時,通過< collection >調用selectEmployeesByDeptId方法,并傳入條件參數。
現在是查詢兩次,員工部門表
員工查員工,部門查部門。
public interface EmployeeDAO {// 查詢某個部門下的所有員工List<Employee> queryEmployeeByDeptId(@Param("deptId") Integer deptId);
}
<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>--><association property="department" javaType="Department"select="com.qf.dao.DepartmentDAO.queryDepartmentById"column="dept_id"<--給到的屬性-->></association></resultMap><select id="queryEmployeeByDeptId" resultType="Employee">select id,name,salaryfrom t_employeeswhere dept_id=#{deptId}</select>
可以查出當前部門下的所有員工。
先查出部門,再通過部門使用查詢員工的方法進行嵌套查詢。
DepartmentDAO mapper = MyBatisUtil.getMapper(DepartmentDAO.class);Department department = mapper.queryDepartmentById(1);System.out.println(department);List<Employee> employees = department.getEmployees();for (Employee employee : employees) {System.out.println(employee);}
反過來查詢員工的部門信息也是可以的
定義selectEmployeesByDeptId,并書寫Mapper,實現根據部門ID查詢員工信息
public interface EmployeeDao {/*** 根據部門編號查詢員工信息* @param did 部門編號* @return 該部門中的所有員工*/public List<Employee> selectEmployeeByDeptId(@Param("did") String did);
}
<mapper namespace="com.qf.mybatis.part2.one2many.EmployeeDao"><!-- 根據部門編號查詢所有員工 --><select id="selectEmployeeById" resultType="employee" >SELECT id,name,salary,dept_id FROM t_employees WHERE dept_id = #{did}</select>
</mapper>
定義selectDepartmentById,并書寫Mapper,實現根據部門ID查詢部門信息,并及聯查詢該部門員工信息
public interface DepartmentDao {/*** 查詢部門信息* @param id* @return*/public Department selectDepartmentById(@Param("id") String id);
}
<mapper namespace="com.qf.mybatis.part2.one2many.DepartmentDao"><resultMap id="departmentResultMap" type="department"><id property="id" column="id" /><result property="name" column="name" /><result property="location" column="location" /><!-- column="傳入目標方法的條件參數" select="及聯調用的查詢目標"--><collection property="emps" ofType="Employee" column="id" select="com.qf.mybatis.part2.one2many.EmployeeDao.selectEmployeeByDeptId" /></resultMap><select id="selectAllDepartments" resultMap="departmentResultMap">SELECT id , name , locationFROM t_departmentsWHERE id = #{id}</select>
</mapper>
mybatis-config.xml中開啟延遲加載
<settings><setting name="lazyLoadingEnabled" value="true"/> <!-- 開啟延遲加載(默認false) -->
</settings>
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态