※別名
上個例子的Dept.xml裡面的resultType,有可能有很多支都回傳一樣的物件,所以可以用別名的方式來對應,據說2.x是在Dept.xml裡設裡,3.x方法是在mybatis-config.xml裡設定,集中起來感覺比較好找,可參考這裡如下:<properties resource="jdbc.properties"></properties> <typeAliases> <typeAlias type="org.mybatis.model.Dept" alias="Dept" /> <package name="org.mybatis.model" /> </typeAliases>
注意如果有「The content of element type "configuration" must match
"(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,plugins?,enviro
nments?,databaseIdProvider?,mappers?)".」這樣的錯,有可能是你沒有按照順序設定,如properties->settings->typeAliases…等
這時Dept.xml就只要寫resultType="Dept"就可以了(不一定要resultType才可以用)
也可以用註解,@Alias("xxx") 寫在 java bean class 的最上面,但要配合掃瞄包,也就是 package name,這別名可以在 xml 使用
都設定不會有問題,都可以用,如果只有掃瞄包,不寫 @Alias,預設是類名稱,開頭大小寫都可以
※增刪改查
Dept.xml如下,注意#{}裡面是對應getter方法的field而parameterType,為傳進去的參數類型; resultType為傳回的結果
雖然getDeptById,我寫int,但我傳Dept整個物件依然可以,不過為了好維護,大家都能看懂的方式,最好寫物件就傳物件,寫int就傳int
<?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="Dept">
SELECT DEPTNO, DNAME, LOC FROM DEPT WHERE DEPTNO = #{deptNo}
</select>
<select id="findAll" resultType="Dept">
SELECT DEPTNO, DNAME, LOC FROM DEPT
</select>
<insert id="insert" parameterType="Dept">
INSERT INTO DEPT(DEPTNO, DNAME, LOC)
VALUES(#{deptNo},#{dName},#{loc})
</insert>
<update id="update" parameterType="Dept">
UPDATE DEPT SET
DNAME = #{dName}
,LOC = #{loc}
WHERE
DEPTNO = #{deptNo}
</update>
<delete id="delete" parameterType="Dept">
DELETE FROM DEPT WHERE DEPTNO = #{deptNo}
</delete>
</mapper>
測試類:注意參數要對應Dept.xml的parameterType
InputStream is = null;
SqlSession sqlSession = null;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(is);
sqlSession = factory.openSession();
// 新增
// System.out.println("----------Dept.insert----------");
// Dept deptIns = new Dept();
// deptIns.setDeptNo(60);
// deptIns.setdName("Sales");
// deptIns.setLoc("zh_CN");
// int suc = sqlSession.insert("Dept.insert", deptIns);
// System.out.println("成功新增" + suc + "筆!");
// 修改
// System.out.println("----------Dept.update----------");
// Dept deptUpd = new Dept();
// deptUpd.setDeptNo(60);
// deptUpd.setdName("Shopping");
// deptUpd.setLoc("zh_CN");
// int upd = sqlSession.update("Dept.update", deptUpd);
// System.out.println("成功修改" + upd + "筆!");
// 刪除
// System.out.println("----------Dept.delete----------");
// Dept deptDel = new Dept();
// deptDel.setDeptNo(60);
// int del = sqlSession.delete("Dept.delete", deptDel);
// System.out.println("成功刪除" + del + "筆!");
// 查詢一筆
System.out.println("----------Dept.getDeptById----------");
//Dept d = new Dept();
//d.setDeptNo(90);
Dept dept = sqlSession.selectOne("Dept.getDeptById", 90);
System.out.println("deptNo=" + dept.getDeptNo());
System.out.println("dName=" + dept.getdName());
System.out.println("loc=" + dept.getLoc());
// 查詢全部
// System.out.println("----------Dept.findAll----------");
// List<Dept> dept = sqlSession.selectList("Dept.findAll");
// for (Dept deptAll : dept) {
// System.out.println("deptNo=" + deptAll.getDeptNo());
// System.out.println("dName=" + deptAll.getdName());
// System.out.println("loc=" + deptAll.getLoc());
// }
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
※xml裡的變數
Dept.xml裡的DEPTNO, DNAME, LOC欄位重覆好幾次,可以統一用一個類似變數的東西控管,如下:<sql id="column">
DEPTNO, DNAME, LOC
</sql>
<select id="getDeptById" parameterType="int" resultType="Dept">
SELECT
<include refid="column" />
FROM DEPT WHERE DEPTNO = #{deptNo}
</select>
<select id="findAll" resultType="Dept">
SELECT
<include refid="column" />
FROM DEPT
</select>
<insert id="insert" parameterType="Dept">
INSERT INTO DEPT(
<include refid="column" />
)
VALUES(#{deptNo},#{dName},#{loc})
</insert>
<update id="update" parameterType="Dept">
UPDATE DEPT SET
DNAME = #{dName}
,LOC = #{loc}
WHERE
DEPTNO = #{deptNo}
</update>
<delete id="delete" parameterType="Dept">
DELETE FROM DEPT WHERE DEPTNO
= #{deptNo}
</delete>
用<sql>標籤當變數,用<include refid="">可取得※MybatisUtil
和Hibernate一樣,每次都要呼叫SessionFactory太麻煩了,所以加上這個類,以下是高手提供的寫法,ThreadLocal(區域執行緒),目的是把變數存在目前的執行緒中, 讓每個執行中的執行緒都有一份, 而且彼此之間不會互相影響package cn.mldn.util;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisSessionFactory {
private static final String CONFIG = "mybatis-config.xml";
//ThreadLocal<SqlSession>讓SqlSession不會重覆被呼叫
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
private static SqlSessionFactory sessionFactory;
private static Reader reader = null;
static {
try {
reader = Resources.getResourceAsReader(CONFIG);
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
private MyBatisSessionFactory() {
}
public static SqlSession getSession() {
SqlSession session = (SqlSession) threadLocal.get();
if (session == null) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
reader = Resources.getResourceAsReader(CONFIG);
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void closeSession() {
SqlSession session = (SqlSession) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
public static SqlSessionFactory getSessionFactory() {
return sessionFactory;
}
public static Reader getConfiguration() {
return reader;
}
}
這樣子呼叫就把sqlSession = factory.openSession();改成sqlSession = MybatisUtil.getSession();
然後try catch拿掉,最後MybatisUtil.closeSession();即可,寫一下好了:
//本來是這樣
InputStream is = null;
SqlSession sqlSession = null;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(is);
sqlSession = factory.openSession();
//CRUD...
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//改成以下模樣
SqlSession sqlSession = MybatisUtil.getSession();
//CRUD...
sqlSession.commit();
MybatisUtil.closeSession();
※傳變數給xml
Map<String, Object> map = new HashMap<String, Object>();
//key要對應Dept.xml
map.put("column", "dname");//欄位名稱
map.put("keyWord", "%a%");//給like尋找的關鍵字
map.put("start", 2);// 從第幾筆
map.put("end", 4);// 到第幾筆
SqlSession session = MybatisUtil.getSession();
System.out.println("AllCount=" + session.selectOne("Dept.getAllCount", map));
List<Dept> all = session.selectList("Dept.findAllBySplit", map);
for(Dept d:all){
System.out.print(d.getDeptNo() + "\t");
System.out.print(d.getdName() + "\t");
System.out.println(d.getLoc());
}
MybatisUtil.closeSession();
Demp.xml這樣設定,我用的是Oracle,所以就要用oracle的語法
<select id="findAllBySplit" parameterType="java.util.Map" resultType="Dept">
SELECT <include refid="column" />
FROM (
SELECT ROWNUM AS RANK, <include refid="column" /> FROM DEPT ORDER BY DEPTNO
)
WHERE
LOWER(${column}) LIKE #{keyWord} AND
RANK BETWEEN #{start} AND #{end}
</select>
<select id="getAllCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(deptno)
FROM DEPT
WHERE LOWER(${column}) LIKE #{keyWord}
</select>
沒有留言:
張貼留言