<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency>
※還要有資料庫驅動程式,oracle 在這裡,可用 SELECT * FROM v$version; 查版本
mybatis和Hibernate都是連資料庫轉換成物件的東東
1.所以一開始先將DB的驅動程式和mybatis的jar放到lib裡
2.寫一隻和DB相關的properties,名稱隨便取,我是叫jdbc.properties,如下
driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@127.0.0.1:1521:orcl username=your account password=your password
3.寫一隻mybatis-config.xml,從這邊copy後,再修改 如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"></properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/model/Dept.xml" /> </mappers> </configuration>
※environments 裡可以寫很多的 environment,譬如 oracle、mysql…等資料庫,改 default 的字串,就可以輕鬆切換
※我知道加這行properties resource,是因為這裡有講,所以也可以將properties的內容寫在裡面或混用
※4.第3步裡面有mapper resource的xml,所以就寫一隻xml吧!檔案名稱可和DB的表名稱不一樣,Dept.xml
<?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="Dept"> <select id="getDeptById" parameterType="int" resultType="org.mybatis.model.Dept"> select * from dept where deptno = #{deptNo} </select> </mapper>
parameterType為傳進去的參數型態是什麼,給#{}接收; resultType為回傳的型態是什麼
5.resultType會連到java,寫一下唄
package org.mybatis.model; public class Dept { private int deptNo; private String dName; private String loc; public int getDeptNo() { return deptNo; } public void setDeptNo(int deptNo) { this.deptNo = deptNo; } public String getdName() { return dName; } public void setdName(String dName) { this.dName = dName; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } }
6.寫一支測試類來測一下,從這裡copy後,稍加修改
public static void main(String[] args) { InputStream is = null; SqlSession sqlSession = null; try { is = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder() .build(is); sqlSession = factory.openSession(); Dept dept = sqlSession.selectOne("Dept.getDeptById", 40); System.out.println("deptNo=" + dept.getDeptNo()); System.out.println("dName=" + dept.getdName()); System.out.println("loc=" + dept.getLoc()); } catch (IOException e) { e.printStackTrace(); } finally { sqlSession.close(); try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } }
※Dept.getDeptById為namespace.id
※如果 java bean 的名稱和資料庫的名稱不一樣,可以用 as 或者使用 <resultMap>,後續會說明
※介面編程
以上是舊的寫法,現在用的是介面來寫,首先寫一個介面,介面定義一些方法,然後 xml 的namespace 寫 interface 的全類名,id 為方法名,這樣就會自動對應了(但不能用overloading),如下:interface
public Dept getDeptById(int id); public Dept getDeptByIdAndLoc(@Param("id") int id, @Param("loc") String loc); public Dept getDeptByList(@Param("ids") List<Integer> ids); public Dept getDeptByMap(Map<String, Object> map); public List<Dept> getListByName(String name); public Map<String, Object> getMapById(int id); @MapKey("deptNo") public Map<Integer, Dept> getMapByName(String name);
xml
<select id="getDeptById" resultType="mp.bean.Dept"> select * from dept where deptno = #{deptNo} </select> <select id="getDeptByIdAndLoc" resultType="mp.bean.Dept"> select * from dept where deptno = #{id} and loc = #{loc} <!-- where deptno = #{param1} --> <!-- and loc = #{param2} --> <!-- where deptno = #{arg0} --> <!-- and loc = #{arg1} --> </select> <select id="getDeptByList" resultType="mp.bean.Dept"> select * from dept where deptno = #{ids[0]} <!-- #{list[0]} --> </select> <select id="getDeptByMap" resultType="mp.bean.Dept"> select * from dept where deptno = #{xxx} and loc = #{loc} </select> <select id="getListByName" resultType="mp.bean.Dept"> select * from dept where dname like #{name} </select> <select id="getMapById" resultType="map"> select * from dept where deptno = #{id} </select> <select id="getMapByName" resultType="mp.bean.Dept"> select * from dept where dname like #{name} </select>
※回傳值寫 map、list 會幫我們對應到 java 常用的類別或介面了,這是因為 mybatis 已經有內鍵的別名了,還有很多,可參考官網
測試類
// Dept dept = sqlSession.selectOne("Dept.getDeptById", 40); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); /* Dept dept = mapper.getDeptById(40); System.out.println("dept=" + dept); System.out.println("deptNo=" + dept.getDeptNo()); System.out.println("dName=" + dept.getdName()); System.out.println("loc=" + dept.getLoc()); */ /* Dept dept = mapper.getDeptByIdAndLoc(40, "BOSTON"); System.out.println("dept=" + dept); */ /* List<Integer> list = new ArrayList<>(); list.add(40); Dept dept = mapper.getDeptByList(list); System.out.println("dept=" + dept); */ /* Map<String, Object> map = new HashMap<>(); map.put("xxx", 40); map.put("loc", "BOSTON"); Dept dept = mapper.getDeptByMap(map); System.out.println("dept=" + dept); */ /* List<Dept> listByName = mapper.getListByName("%O%"); System.out.println(listByName);//找不到不是null,是空的 list listByName.forEach((dept) -> { System.out.println(dept.getdName()); }); */ /* Map<String, Object> mapById = mapper.getMapById(40); System.out.println(mapById);// 找不到為null */ Map<Integer, Dept> mapByName = mapper.getMapByName("%O%"); System.out.println(mapByName);// 找不到不是null,是空的 map
※注意:
1.parameterType 可不寫,mybatis 會用TypeHandler 自動判斷
2.傳一個參數時,#{} 裡面可以隨便寫
傳多個參數時,第一個參數可寫 args0 或 param1,第二個參數可寫 args1 或 param2…依此類推,但如果配合 @Param 時,只能寫 @Param 的值和 paramX,就不能寫 argsX 了
錯誤訊息有提示 Available parameters are [arg1, arg0, param1, param2]
3.回傳值是 List 或 Set 時,查詢不到返回的是空 list,不是 null
4.回傳值是 Map 時,如果泛型沒有 java bean 查詢不到時會回傳 null;但如果有 java bean,會回傳空 map
5.List、Map 裡的泛型有 java bean,在 xml 裡的 resultType 也要寫 java bean 才可以,否則List 會出 java.lang.UnsupportedOperationException 的錯; Map 只有一筆
6.mybatis-config.xml 的 mappers 標籤的 mapper resource 除了可以一次設定一個 xml 路徑外,還可以用掃瞄包的方式 package name="mp.bean.dao" 一次就抓很多的 xml 了,但要注意 xml 必須放在和 interface 同一層目錄(下一層也不行)且同名才行
或者在 interface 使用 @Mapper 也行,但因為沒有 SQL了,還得加上類似 @Select 的註解即可
7.如果參數是物件,xml 裡直接寫屬性名即可,但如果加了 @Param,那就只能用 param1或@Param 裡面的字串
※在 Console 印 SQL
mybatis 支援很多 log,可看官網,這裡以 log4j2 為例1.取得 jar 檔,推薦用 maven、gradle 等
2. 寫 log4j2.xml 放在 classpath 目錄下,然後將 Root level 放 DEBUG 以上層級
以上兩個可參考我 log4j2 的文章,其中第 2 步有很多做法,我是用官網自動設定的第9招
3.mybatis 設定 <setting name="logImpl" value="LOG4J2" /> 即可
※typeAliases 使用 package name 時會有亂碼,不知道為什麼,不過不影響 SQL 就是了
有興趣的可以看源碼的 DefaultVFS 的 list 方法,第二個 for 迴圈
setting 的設定很多,可看官網
沒有留言:
張貼留言