Mybatis --- 映射文件、參數處理、參數值的獲取、select元素

映射文件:指導着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>

編寫測試單元:java

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", "zhangsan@q.com");
      mapper.insertEmp(emp);
      int id = emp.getId();
      System.out.println(id);
}
@After
public void testAfter(){
      //增刪改須要提交事務
      session.commit();
      session.close();
}
//@Before、@After自動在@Test以前和以後運行
//查詢不須要提交事務,增刪改都須要提交事務

 

2.獲取自增主鍵值【當向數據庫中插入一條數據的時候,默認是拿不到主鍵的值的, 須要設置以下兩個屬性才能夠拿到主鍵值!】mysql

<!--設置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參數:若是多個參數正好是咱們業務邏輯的數據模型,咱們就能夠直接傳入POJOsql

  #{屬性名}:取出傳入的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語句中,會有安全問題session

<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.返回記錄爲一個Mapmybatis

   只能查詢單條數據,若是多條的話,多個key 值,找不到app

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);
}
相關文章
相關標籤/搜索