<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 的設定很多,可看官網
沒有留言:
張貼留言