映射文件:指導著MyBatis如何進行資料庫增刪改查, 有著非常重要的意義; - cache 命名空間的二級緩存配置 - cache-ref 其他命名空間緩存配置的引用。 - resultMap 自定義結果集映射 - parameterMap 已廢棄!老式風格的參數映射 - sql 抽取可重用語句塊 ...
映射文件:指導著MyBatis如何進行資料庫增刪改查, 有著非常重要的意義; - cache 命名空間的二級緩存配置 - cache-ref 其他命名空間緩存配置的引用。 - resultMap 自定義結果集映射 - parameterMap 已廢棄!老式風格的參數映射 - sql 抽取可重用語句塊 - insert 映射插入語句 - update 映射更新語句 - delete 映射刪除語句 - select 映射查詢語句 1.先看增刪改查標簽
public interface EmployeeMapper { /* * 增刪改查方法 * */ public Employee getEmployeeById(Integer id); public void insertEmp(Employee employee); }在其對應的sql映射文件中: useGeneratedKeys="true":預設使用主鍵自增的主鍵 keyProperty="id":將主鍵賦值給 id 屬性 這樣就可以在insert函數中獲取新添加的用戶的 id主鍵,否則獲取不到
<select id="getEmployeeById" resultType="employee" databaseId="mysql"> select * from student where id = #{id} </select> <insert id="insertEmp" parameterType="com.neuedu.entity.Employee" useGeneratedKeys="true" keyProperty="id"> insert into student(name,password,email) values(#{name},#{password},#{email}) </insert>
編寫測試單元:
private EmployeeMapper mapper = null; private SqlSession session = null; @Before public void testBefore(){ //1.獲取sqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //2.利用sqlSessionFactory創建一個session對象,表示和資料庫的一次會話 session = sqlSessionFactory.openSession(); //3.用session對象獲取mapper介面的代理對象 //因為sql映射文件給相應的介面創建了一個代理對象,所以mapper介面類不需要實現類 mapper = session.getMapper(EmployeeMapper.class); } @Test public void testSelect(){ mapper = session.getMapper(EmployeeMapper.class); //4.通過mapper介面的代理對象就可以對資料庫進行增刪改查操作 Employee employee = mapper.getEmployeeById(4); System.out.println(employee); } @Test public void testInsert(){ Employee emp = new Employee("zhangsan", "1234567", "[email protected]"); mapper.insertEmp(emp); int id = emp.getId(); System.out.println(id); } @After public void testAfter(){ //增刪改需要提交事務 session.commit(); session.close(); } //@Before、@After自動在@Test之前和之後運行 //查詢不需要提交事務,增刪改都需要提交事務
2.獲取自增主鍵值【當向資料庫中插入一條數據的時候,預設是拿不到主鍵的值的, 需要設置如下兩個屬性才可以拿到主鍵值!】
<!--設置userGeneratedKeys屬性值為true:使用自動增長的主鍵。使用keyProperty設置把主鍵值設置給哪一個屬性--> <insert id="addEmp" parameterType="com.neuedu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id" databaseId="mysql"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{gender},#{email}) </insert>
3.SQL節點: 1).可以用於存儲被重用的SQL片段 2).在sql映射文件中,具體使用方式如下:
<sql id="npe"> name,password,email </sql> <insert id="insertEmp" parameterType="com.neuedu.entity.Employee" useGeneratedKeys="true" keyProperty="id"> insert into student(<include refid="npe"></include>) values(#{name},#{password},#{email}) </insert>
參數處理: - 單個參數:Mybatis 不會特殊處理 #{參數名}: 取出參數值,參數名任意寫 - 多個參數:Mybatis會做特殊處理,多個參數會被封裝成一個map key:param1...paramN,或者參數的索引也可以(0,1,2,3.....) value:傳入的參數值 #{ }就是從map中獲取指定的key的值 命名參數:明確指定封裝參數時map的key:@param("id") 多個參數會被封裝成一個map, key:使用@Param註解指定的值 value:參數值 #{指定的key}取出對應的參數值
public void updateEmp(@Param("id")Integer id, @Param("name")String name, @Param("password")String password, @Param("email")String email);
<update id="updateEmp"> update student set name=#{name},password=#{password},email=#{email} where id=#{id} </update>
- POJO參數:如果多個參數正好是我們業務邏輯的數據模型,我們就可以直接傳入POJO
#{屬性名}:取出傳入的POJO的屬性值
public void insertEmp(Employee employee);
<sql id="npe"> name,password,email </sql> <insert id="insertEmp" parameterType="com.neuedu.entity.Employee" useGeneratedKeys="true" keyProperty="id"> insert into student(<include refid="npe"></include>) values(#{name},#{password},#{email}) </insert>
@Test public void testReturnVal(){ Employee employee = mapper.getEmployeeById(30); System.out.println(employee); }
- Map:如果多個參數不是業務模型中的數據,沒有對應的pojo,不經常使用,為了方便,我們也可以傳入Map
#{key}:根據 key 取出map中對應的值
public void updateName(Map<String, Object> map);
<update id="updateName"> update student set name=#{name} where id=#{id} </update>
@Test public void testMap(){ Map<String, Object> map = new HashMap<>(); map.put("id", 33); map.put("name", "劉德華"); mapper.updateName(map); }
#關於參數的問題: ①.使用#{}來傳遞參數 ②.若目標方法的參數類型為對象類型,則調用其對應的getter方法,如getEmail() ③.若目標方法的參數類型為Map類型,則調用其get(key) ④.若參數是單個的,或者列表,需要使用@param註解來進行標記 ⑤.註意:若只有一個參數,則可以省略@param註解 若有多個參數,必須要寫@param註解
參數值的獲取: #{}:可以獲取map中的值或者pojo對象屬性的值
${}: 可以獲取map中的值獲取pojo對象屬性的值 用例子簡單區分一下: select * from tbl_employee where id = ${id} and last_name = #{lastName}
preparing:select * from tbl_employee where id = 2 and last_name = ? 也就是說:對於${} 在日誌中可以看到你輸入的值,不安全; 對於#{} 在日誌中是?,所以相對安全 具體區別: #{}:是以預編譯的形式,將參數設置到sql語句中,相當於PreparedStatement;防止sql註入
<update id="updateEmp"> update student set name=#{name},password=#{password},email=#{email} where id=#{id} </update>
${}:取出的值直接拼裝在sql語句中,會有安全問題
<update id="updateEmp"> update student set name='${name}',password='${password}',email='${email}' where id='${id}' </update>
大多情況下,我們取參數的值都應該去使用#{} 但是原生JDBC不支持占位符的地方我們就可以使用${}進行取值 比如獲取表名、分表、排序;按照年份分表拆分 - select * from ${year}_salary where xxx;[表名不支持預編譯] - select * from tbl_employee order by ${f_name} ${order} :排序是不支持預編譯的!
select 元素 : select元素來定義查詢操作。 Id:唯一標識符。 用來引用這條語句,需要和介面的方法名一致 parameterType:參數類型。 可以不傳,MyBatis會根據TypeHandler自動推斷 resultType:返回值類型。 別名或者全類名,如果返回的是集合,定義集合中元素的類型。不能和resultMap同時使用 1.返回類型為一個List
public List<Employee> getEmps();
<select id="getEmps" resultType="com.neuedu.entity.Employee"> select * from student </select>
@Test public void testReturnList(){ List<Employee> emps = mapper.getEmps(); for (Employee employee : emps) { System.out.println(employee); } }
2.返回記錄為一個Map
只能查詢單條數據,如果多條的話,多個key 值,找不到
public Map<String, Object> getEmpInfoById(Integer id);
resultType 是 Map 的全類名
<select id="getEmpInfoById" ="java.util.Map"> select * from student where id = #{id} </select>
key:列名;value:值
@Test public void testReturnMap(){ Map<String, Object> emp = mapper.getEmpInfoById(30); Set<Entry<String,Object>> entrySet = emp.entrySet(); for (Entry<String, Object> entry : entrySet) { System.out.println(entry.getKey()+":"+entry.getValue()); } }
資料庫列名與實體類的屬性名不對應的情況下有幾種處理方式: 1.sql 語句 用 as 換名 2.下劃線轉換成駝峰式命名 在全局配置文件中
<settings> <!-- setting標簽負責每一個屬性的設置 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
3.利用ResultMap:
public Employee getEmpInfoById(Integer id);
<resultMap type="com.neuedu.entity.Employee" id="getEmployByIdMap"> <!-- 主鍵映射可以用 id 欄位,mybatis在底層會做優化,主鍵有索引,加快查詢速度 --> <id column="id" property="id"/> <!-- 普通列的映射使用result --> <result column="name" property="name"/> <result column="password" property="password"/>//相同的也可以不寫,但因為規範建議寫 <result column="email" property="email"/> </resultMap> <select id="getEmpInfoById" resultMap="getEmployByIdMap"> select * from student where id = #{id} </select>
@Test public void testReturnMap(){ Employee emp = mapper.getEmpInfoById(30); System.out.println(emp); }