Mybatis對映檔案(1)
mybatis對映檔案——增刪改查
public interface EmployeeMapper { Employee selectById(Integer id); void addEmp(Employee employee); void updateEmp(Employee employee); void deleteEmpById(Integer id); }
<mapper namespace="dao.EmployeeMapper"> <select id="selectById" resultType="employee">SELECT * FROM t_employee WHERE id = #{id} </select> <!--parameterType可以省略--> <insert id="addEmp" parameterType="bean.Employee"> INSERT INTO t_employee VALUES (NULL ,#{lastName},#{gender},#{email}) </insert> <update id="updateEmp"> UPDATE t_employee SET last_name= #{lastName},gender=#{gender},email = #{email} WHERE id=#{id} </update> <delete id="deleteEmpById"> DELETE FROM t_employee WHERE id=#{id} </delete> </mapper>
/** *1、 mybatis 允許增刪改查直接定義一下返回值型別 * Long、Integer、Boolean *2、我們需要手動提交資料 * sqlSessionFactory.openSession()===》手動提交 * sqlSessionFactory.openSession(true)===》自動提交* @throws IOException */ @Test public void testSelect() throws IOException { SqlSession sqlSession = getSqlSession(); try { //3、獲取Employee的代理物件——通過sqlSession為介面建立一個代理物件 EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); //增刪改查 mapper.addEmp(new Employee(null, "haha", "1", "[email protected]")); mapper.deleteEmpById(3); mapper.updateEmp(new Employee(1, "tona", "1", "[email protected]")); Employee e = mapper.selectById(2); System.out.println(e); } finally { //4、關閉SqlSession物件 sqlSession.close(); } }
獲取自增主鍵值的策略
自增的資料庫:MySQL
<!-- parameterType可以省略 mybatis支援自增主鍵、自增主鍵的獲取,mabatis也是利用statement.getGenereatedKeys() useGeneratedKeys="true"使用主鍵自增獲取主鍵值策略 keyProperty:指定對應的主鍵屬性,也就是mybatis獲取到主鍵後,將這個值封裝給JavaBean的那個屬性 --> <insert id="addEmp" parameterType="bean.Employee" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_employee(last_name, gender, email) VALUES (#{lastName},#{gender},#{email}) </insert>非自增的資料庫:如Oracle
<!--oracle資料庫不支援自增--> <!--使用Oracle--> <insert id="addEmp" parameterType="bean.Employee" databaseId="oracle"> /* 查詢主鍵的sql語句 keyProperty:查出主鍵封裝給javaBean的那個屬性 order="BEFORE":當前sql在插入sql之前執行 AFTER:當前sql在插入sql之後執行 resultType:查詢出的資料的返回值型別 */ <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> SELECT EMPLOYEES_SEQ.nextval FROM dual </selectKey> INSERT INTO t_employee(EMPLOYEE_ID,last_name, gender, email) VALUES (#{id},#{lastName},#{gender},#{email}) </insert>
mybatis引數處理
單個引數:mybatis不會做任何處理
#{引數名}:取出引數的值
多個引數:mybatis會做特殊處理
多個引數會被封裝成一個map
key:param1,。。。。,paramN或者引數的索引也可以
value:傳入的引數值 #{ }就是從map中獲取指定的key值
Employee selectByIdAndLastName(Integer id,String lastNae);
<select id="selectByIdAndLastName" resultType="employee"> SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName} </select>出現異常: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
改成:
<select id="selectByIdAndLastName" resultType="employee"> SELECT * FROM t_employee WHERE id = #{param1} AND last_name=#{param2} </select>
程式執行OK。
推薦:
命名引數:明確指定封裝引數時的map的key:
@Param("id")
多個引數會被封裝成一個map
key:使用@Param註解指定的值
value:引數值
#{ }取出對應的引數值
Employee selectByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);
<select id="selectByIdAndLastName" resultType="employee"> SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName} </select>
POJO:
如果多個引數正好時我們業務邏輯的資料模型,我們可以直接傳入pojo
#{屬性名}:取出傳入的pojo的屬性值
Map:
如果多個引數不是業務模型中的資料,沒有對應的pojo,不經常使用,為了方便,我們也可以傳入map
#{key}:取出map對應的值
TO:
如果多個引數不是業務模型中的資料,但是經常要使用,推薦來編寫一個TO(Transfer Object)資料傳輸物件
Page{
int index;
int size;
}
============小結==============
Employee getEmp(@Param("id") Integer id,String lastName); 取值:id==》#{id/param1} lastName==》#{param2}
Employee getEmp(@Param("id") Integer id,@Param("e") Employee emp); 取值:id==》#{param1} lastName==》#{param2.lastName/e.lastName}
###特別注意:如果是Collection(List,Set)型別或者是陣列,也會特殊處理。也是把傳入的list或陣列封裝在map中 key:Collection(collection),如果是List還可以使用key(list),陣列(array) Employee getEmpById(List<Integer> ids); 取值:取出第一個值id==》#{ids[0]}
==============原始碼——mybatis對引數的處理==============
public class ParamNameResolver { private static final String GENERIC_NAME_PREFIX = "param"; /** * 存放參數個數 */ private final SortedMap<Integer, String> names; private boolean hasParamAnnotation; //解析引數封裝成map public ParamNameResolver(Configuration config, Method method) { final Class<?>[] paramTypes = method.getParameterTypes(); final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap<Integer, String> map = new TreeMap<Integer, String>(); int paramCount = paramAnnotations.length; // get names from @Param annotations //索引引數 for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { // skip special parameters continue; } String name = null; //如果當前引數的註解為@Param註解 for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { hasParamAnnotation = true; name = ((Param) annotation).value();//獲取引數的值 break; } } if (name == null) { // @Param was not specified. if (config.isUseActualParamName()) { name = getActualParamName(method, paramIndex); } if (name == null) { // use the parameter index as the name ("0", "1", ...) // gcode issue #71 name = String.valueOf(map.size());//如果麼有標註解就是map } } map.put(paramIndex, name);//放入 } names = Collections.unmodifiableSortedMap(map); } private String getActualParamName(Method method, int paramIndex) { if (Jdk.parameterExists) { return ParamNameUtil.getParamNames(method).get(paramIndex); } return null; } private static boolean isSpecialParameter(Class<?> clazz) { return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz); } /** * Returns parameter names referenced by SQL providers. */ public String[] getNames() { return names.values().toArray(new String[0]); } /** * names (param1, param2,...). * </p> */ public Object getNamedParams(Object[] args) { final int paramCount = names.size();//獲取引數個數 if (args == null || paramCount == 0) { return null;//引數為null直接返回 //如果只有一個元素,並且沒有param註解,直接返回args[0],單個元素直接返回 } else if (!hasParamAnnotation && paramCount == 1) { return args[names.firstKey()]; } else { final Map<String, Object> param = new ParamMap<Object>(); int i = 0; //給上面新建的param這個map儲存資料——遍歷names集合 for (Map.Entry<Integer, String> entry : names.entrySet()) { //names集合的value值作為key,names集合的key又作為取值的參考 //如:names集合{0=id,1=lastName}===》{id=args[0]:1,lastName=args[1]:toma} param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) //額外的將每個引數儲存到map中,使用新的key:param1,param2。。。。paramN final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1); // ensure not to overwrite parameter named with @Param if (!names.containsValue(genericParamName)) { param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } } }
ParamNameResolver解析引數封裝map的:
1、names獲取引數(0=id,1=lastName)
2、獲取每個表了@param註解的引數的值:id、lastName,賦值給name
3、每次解析一個引數給map中儲存資訊:(key:引數索引,value:name的值)
name的值:標註了param註解:註解的值
沒有標註:1、全域性配置isUseActualParamName(JDK1.8才行):name=引數名
2、name=map.size()——相當於當前元素的索引
===============關於引數的獲取================
#{ }:可以獲取map中的值或者pojo物件中的值
${ }:可以獲取map中的值或者pojo物件中的值
區別:
<select id="selectByIdAndLastName" resultType="employee"> SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName} </select>執行的sql語句為: Preparing: SELECT * FROM t_employee WHERE id = ? AND last_name=?
<select id="selectByIdAndLastName" resultType="employee"> SELECT * FROM t_employee WHERE id = ${id} AND last_name=#{lastName} </select>
執行的sql語句為:Preparing: SELECT * FROM t_employee WHERE id = 1 AND last_name=?
#{ }:是以預編譯的形式將引數設定到sql語句中,PrepareStatement。防止sql注入
${ }:將取出的值直接拼裝在sql中。會有安全問題
大多數情況下,我們取引數的值都應該使用#{ }
但是在原生jdbc不支援佔位符的地方就可以使用${ }進行取值
比如:分表:按照年份分表拆分
select * from ${year}_salary where xxxx
select * from employ order by ${ name } ${ desc/asc}——排序
#{ }:更豐富的用法:
規定一些規則:
javaType、jdbcType、mode(儲存過程)、numericScale(小數位數)、
resultMap(結果集)、 typeHandler(型別處理器)、jdbcTypeName、express
jdbcType:通常需要在某些特定的條件下被設定:在我們資料為null的時候,有些資料庫可能不能識別mybatis對null的預設處理,比如oracle(報錯)——JdbcType OTHER:無效型別,因為mybatis對所有的null都對映的是原生jdbc的 Other型別
由於全域性配置中:jdbcTypeForNull=OTHER,Oracle不支援:——兩種解決:
1、#{ 引數,jdbcType=OTHER} 2、在全域性配置檔案中設定:jdbcTypeForNull=NULL
<setting name="jdbcTypeForNull" value="NULL"></setting>
相關推薦
Mybatis對映檔案(1)
mybatis對映檔案——增刪改查public interface EmployeeMapper { Employee selectById(Integer id); void addEmp(Employee employee); void updat
JavaEE-SSM:010 Mybatis對映器(1)
對映器綜述 對映器是建立Mapper介面函式和Sql語句之間聯絡的關鍵部件,它可以指定POJO型別,也可以指定JDBC型別,同時,也可以指定TypeHandler對其轉換。可以對映Mapper介面函式引數:parameterType,也可對映結果引數ResultType或者Re
Mybatis對映檔案(3)
動態SQL1、if/where<!-- test:判斷表示式(OGNL自己去查怎麼用) test="id != null":從引數中取值進行判斷 拼裝的時候有的條件沒帶可能
Mybatis原始碼分析(1)—— Mapper檔案解析
感覺CSDN對markdown的支援不夠友好,總是伴隨各種問題,很惱火! xxMapper.xml的解析主要由XMLMapperBuilder類完成,parse方法來完成解析: public void parse() { if (!configuration.isRes
MyBatis原始碼分析(1)-MapConfig檔案的解析
1.簡述 MyBatis是一個優秀的輕ORM框架,由最初的iBatis演化而來,可以方便的完成sql語句的輸入輸出到java物件之間的相互對映,典型的MyBatis使用的方式如下: String resource = "org/mybatis/example/mybatis-config.xml";
Mybatis學習筆記(1)——第一個程式
暑期之前就有打算學習SSM,但是我記得當時再配置一個框架瘋狂報錯,弄得我很難受,,再加上當時有點其他事情,所以就放了下來。現在很有需求要會ssm,所以就學了一下。感覺框架這東西配置就煩的要死。錯一丁點就全錯。。下面開始說配置詳情。 介紹一下這些東西,將mybatis的jar包依賴放
JavaEE-SSM:014 Mybatis對映器(5)
ResultMap子元素一覽 <constructor>節點配置 假如,我們返回型別的POJO不包含無參建構函式,只有一個下面的有參構造: public class RoleBean { public Rol
JavaEE-SSM:013 Mybatis對映器(4)
SQL節點:一次定義,多次呼叫 先定義SQL節點:id用於參考 <sql id="preSql"> id,role_name,note </sql> 使用SQL: 通過include節點並指定refid,refid是
JavaEE-SSM:012 Mybatis對映器(3)
1.insert節點配置資訊一覽 id用於Mapper介面函式的對應 parameterType指的是SQL語句的輸入引數 useGeneratedKeys自動產生主鍵 keyProperty主鍵欄位 KeyColumn主鍵列名 2.
JavaEE-SSM:011 Mybatis對映器(2)
Select配置語句常用配置 常用的配置已經圈出: id:配合Mapper對映介面使用,一般和介面函式名稱一致 parameterType:輸入引數的型別 resultType:輸出引數的型別 ResultMap:輸出對映集 flushCache:清空快取
Redis配置檔案(1)units/includes/GENERAL/SECURITY/LIMITS
redis.conf檔案 在Linux進行檔案的檢視! units單位: 8 # Note on units: when memory size is needed, it is possible to specify 9 # it in the usual form
MyBatis學習筆記(1)---一個簡單MyBatis示例
利用JDBC仍舊存在的幾個侷限性: 在應用程式中存在的大量程式碼冗餘。 業務程式碼與資料庫訪問程式碼混雜在一起。 SQL語句與Java程式碼混雜在一起。 JDBC丟擲費力難懂的checked異常,需要程式設計師花費精力小心處理。 需要程式設計師自行解決ORM
Windows應用程式打包成exe檔案(1)- 工具簡單總結
最近有對一個Windows應用程式少許維護和修改。修改之後要釋出新的exe安裝檔案,打包exe檔案時,遇到了很頭疼的問題,還好最後解決了,記錄一下。 Visual Studio版本:Visual Studio 2017 Visual Studio 201
servlet載入配置檔案(1)
大三期間,和老師一起寫專案,發現一些小的技巧是之前沒有實現過:使用servlet啟動載入配置檔案,然後通過反射獲取物件的做法可以值得今後學習借用: <servlet> &
Mybatis配置檔案(一)
Mapper檔案中各個標籤的含義Mapper檔案是Mybatis中SQL語句的配置檔案,其在執行時會載入SQL語句並對映相應引數。熟悉各個標籤的含義便於理解專案中DAO層相關函式的實際意義。屬性含義idSQL對映配置的唯一標識。parameterType傳入SQL配置中的引數
mybatis面試總結(1)——介紹mybatis
如果面試官直接讓我介紹mybatis,我將從以下幾個方面去介紹這個框架: 1.mybatis是什麼? mybatis是一個優秀的持久層框架,他對jdbc操作資料庫的過程進行了封裝,使
myBatis學習筆記(1)——快速入門
在專案中使用myBatis 匯入jar包 在src下建立配置檔案 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis
MyBatis原始碼學習(1)
MyBatis環境搭建 最近開始準備學習MyBatis的原始碼,第一件事當然就是搭建環境。 JDK:1.8 IDE:Idea mysql:8.0.11 首先需要安裝Git,正常下載安裝就可以,然後需要在Idea中配置一下,如下 圖:
深入Hibernate對映檔案(二)——的屬性
<hibernate-mapping>根元素中可以指定以下屬性: (1)schema: 制定所對映的資料庫的Schema名, ()catalog ()default-casade:設定Hibernate預設的級聯風格,該屬性的預設值是none。當配置之Java屬
F28335的InitSysCtrl()與DSP2833x_SysCtrl.c檔案(1)
開發DSP除了CCS之外,TI還推出了一個controlSUITE,專門針對C2000系列,主要是官網資源的集中和分類。軟體免費只需要下載安裝,由於不喜歡被別人加工註釋了程式碼與工程,所以controlSUITE是個不錯的選擇。而且裡邊是TI原裝的東西,所以應該是最精華的!開