MyBatis的sql對映檔案(CRUD和主鍵id生成)
一個好的講解mybatis的部落格地址http://www.jianshu.com/nb/5226994
官方文件:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
Mapper XML 檔案
MyBatis 的真正強大在於它的對映語句,也是它的魔力所在。由於它的異常強大,對映器的 XML 檔案就顯得相對簡單。如果拿它跟具有相同功能的 JDBC 程式碼進行對比,你會立即發現省掉了將近 95% 的程式碼。MyBatis 就是針對 SQL 構建的,並且比普通的方法做的更好。
SQL 對映檔案有很少的幾個頂級元素(按照它們應該被定義的順序):
- cache – 給定名稱空間的快取配置。
- cache-ref – 其他名稱空間快取配置的引用。
- resultMap – 是最複雜也是最強大的元素,用來描述如何從資料庫結果集中來載入物件。
parameterMap– 已廢棄!老式風格的引數對映。內聯引數是首選,這個元素可能在將來被移除,這裡不會記錄。- sql – 可被其他語句引用的可重用語句塊。
- insert – 對映插入語句
- update – 對映更新語句
- delete – 對映刪除語句
- select – 對映查詢語句
全域性對映檔案
<?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> <!-- 1. 匯入資原始檔 --> <properties resource="application.properties"></properties> <settings> <!-- 開啟自動駝峰命名規則對映,即從經典資料庫列名 A_COLUMN 到POJO類屬性名 aColumn的類似對映。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!-- 2. 配置資料庫的連線環境(default為id的值),即預設載入的資料庫環境 --> <environments default="mysql"> <environment id="mysql"> <!-- 配置具體的資料庫環境 id唯一 --> <transactionManager type="JDBC" /> <!-- 指定使用的事務處理管理器 --> <dataSource type="POOLED"> <!-- 指定使用的資料來源連線池 --> <property name="driver" value="${jdbc.driverClass}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> <environment id="oracle"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${oracle.driverClass}" /> <property name="url" value="${oracle.url}" /> <property name="username" value="${oracle.user}" /> <property name="password" value="${oracle.password}" /> </dataSource> </environment> </environments> <!-- 3. 引入mapper對映檔案 --> <mappers> <package name="cn.jq.mybatis.dao" /> </mappers> </configuration>
application.properties 檔案
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf8&useSSL=true
jdbc.user=root
jdbc.password=123456
oracle.driverClass=oracle.jdbc.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
oracle.user=scott
oracle.password=tiger
一、簡單增刪改查操作
1、 對映介面實現類
public interface UserMapper {
/**
*
* 根據id查詢一條記錄
* @param id
* @return
*/
//@Select("select * from t_user where id = #{id}")
public User getUser(Integer id);
/**
* 查詢資料庫中的記錄總條數
* @return
*/
public int selectCount();
/**
* 新增一條記錄
* @param user
* @return 資料庫受影響的行數
*/
public int insertUser(User user);
/**
* 刪除一條記錄
* @param id
* @return 資料庫受影響的行數
*/
public int deleteUser(Integer id);
/**
* 修改一條記錄
* @param user
* @return 資料庫受影響的行數>=1 返回true 否則返回false
*/
public boolean updateUser(User user);
/**
* 查詢所有記錄
* @return List<User>
*/
public List<User> selectUserAll();
}
2、sql對映檔案
<?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">
<!-- namespace - 名稱空間對應對映介面的全限定名 -->
<mapper namespace="cn.jq.mybatis.dao.UserMapper">
<!-- id - 對應介面中的方法名
resultType - 從這條語句中返回的期望型別的類完全限定名或別名
parameterType - 傳入這條語句的引數類的完全限定名或別名 -->
<select id="getUser" resultType="cn.jq.mybatis.model.User">
select * from t_user where id = #{id}
</select>
<select id="selectCount" resultType="int">
select count(*) from t_user
</select>
<insert id="insertUser" parameterType="cn.jq.mybatis.model.User">
insert into t_user(username,pazzword,state,reg_date) values(#{username},#{pazzword},#{state},#{regDate})
</insert>
<delete id="deleteUser" parameterType="int">
delete from t_user where id=#{id}
</delete>
<update id="updateUser" parameterType="cn.jq.mybatis.model.User">
update t_user set username=#{username},pazzword=#{pazzword},state=#{state},reg_date=#{regDate} where id=#{id}
</update>
<!-- 返回型別為集合時,resultType只需指定List中單行記錄的型別即可
resultType - 從這條語句中返回的期望型別的類完全限定名或別名 -->
<select id="selectUserAll" resultType="cn.jq.mybatis.model.User">
select * from t_user
</select>
</mapper>
3、測試類
@Test
public void test() throws IOException {
//1. 建立SqlSessionFacotry工廠類物件,根據讀取全域性配置檔案
Resources.setCharset(Charset.forName("utf-8"));//設定編碼格式
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 開啟資料庫連線會話
SqlSession session = sqlSessionFactory.openSession();
try {
//3.通過會話操作sql 返回的是代理物件 jdk動態代理
UserMapper userMapper = session.getMapper(UserMapper.class);
//查詢一條記錄
User user = userMapper.getUser(2);
//查詢資料庫中的記錄總條數
int count = userMapper.selectCount();
//查詢所有記錄
List<User> userlist = userMapper.selectUserAll();
System.out.println(count);
System.out.println(user);
System.out.println(Arrays.asList(userlist));
//新增一條記錄
User user2 = new User("李四", "123456", 1, new Date());
int i = userMapper.insertUser(user2);
System.out.println("成功新增"+i+"條資料");
session.commit(); //提交事務
//修改一條記錄
User user3 = new User();
user3.setId(3);
user3.setUsername("li33");
user3.setPazzword("li33qq");
user3.setState(0);
user3.setRegDate(new Date());
boolean b = userMapper.updateUser(user3);
session.commit();
System.out.println("成功修改"+b+"條資料");
//刪除一條記錄
int n = userMapper.deleteUser(13);
session.commit();
System.out.println("成功刪除"+n+"條資料");
System.out.println(userMapper.selectCount());
} finally {
//關閉會話
session.close();
}
}
----
3
User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018]
[[User [id=1, username=admin, pazzword=172eee54aa664e9dd0536b063796e54e, state=1, regDate=Sun Oct 14 00:00:00 CST 2018], User [id=2, username=user, pazzword=3be7f713d9321e812231bb838448385d, state=1, regDate=Mon Oct 15 00:00:00 CST 2018], User [id=3, username=阿斯達, pazzword=d0dbbe3c3b4d61ef587448bbdc103de7, state=1, regDate=Tue Oct 23 00:00:00 CST 2018]]]
成功新增1條資料
成功修改true條資料
成功刪除1條資料
4
注意:CRUD是可以直接設定返回值的,int, long, boolean 和 void 都可以是返回值型別,int 和long返回影響資料庫條數,boolean影響的條數大於1返回true,否則返回false.
標籤屬性:
屬性 | 描述 |
---|---|
id | 在名稱空間中唯一的識別符號,可以被用來引用這條語句。 |
parameterType | 將會傳入這條語句的引數類的完全限定名或別名。這個屬性是可選的,因為 MyBatis 可以通過 TypeHandler 推斷出具體傳入語句的引數,預設值為 unset。 |
resultType | 從這條語句中返回的期望型別的類的完全限定名或別名。注意如果是集合情形,那應該是集合可以包含的型別,而不能是集合本身。使用 resultType 或 resultMap,但不能同時使用。 |
resultMap | 外部 resultMap 的命名引用。結果集的對映是 MyBatis 最強大的特性,對其有一個很好的理解的話,許多複雜對映的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同時使用。 |
flushCache | 將其設定為 true,任何時候只要語句被呼叫,都會導致本地快取和二級快取都會被清空,預設值:false。 |
useCache | 將其設定為 true,將會導致本條語句的結果被二級快取,預設值:對 select 元素為 true。 |
timeout | 這個設定是在丟擲異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為 unset(依賴驅動)。 |
fetchSize | 這是嘗試影響驅動程式每次批量返回的結果行數和這個設定值相等。預設值為 unset(依賴驅動)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,預設值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一個,預設值為 unset (依賴驅動)。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 會載入所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 |
resultOrdered | 這個設定僅針對巢狀結果 select 語句適用:如果為 true,就是假設包含了巢狀結果集或是分組了,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的情況。這就使得在獲取巢狀的結果集的時候不至於導致記憶體不夠用。預設值:false。 |
resultSets | 這個設定僅對多結果集的情況適用,它將列出語句執行後返回的結果集並每個結果集給一個名稱,名稱是逗號分隔的。 |
useGeneratedKeys | (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由資料庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關係資料庫管理系統的自動遞增欄位),預設值:false。 |
keyProperty | (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設定它的鍵值,預設:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
keyColumn | (僅對 insert 和 update 有用)通過生成的鍵值設定表中的列名,這個設定僅在某些資料庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設定。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
order | 這可以被設定為 BEFORE 或 AFTER。如果設定為 BEFORE,那麼它會首先選擇主鍵,設定 keyProperty 然後執行插入語句。如果設定為 AFTER,那麼先執行插入語句,然後是 selectKey 元素 - 這和像 Oracle 的資料庫相似,在插入語句內部可能有嵌入索引呼叫。 |
二、獲取新增記錄生成主鍵id值
1、Mysql生成主鍵id
資料庫支援自動生成主鍵的欄位(比如 MySQL 和 SQL Server),設定 useGeneratedKeys=”true”,然後再把 keyProperty 設定到目標屬性上就OK。
<!-- mysql資料庫 :資料庫本身有自動生成主鍵的方式
useGeneratedKeys - true 設定使用資料庫本身的功能設定主鍵
keyProperty - 設定在model物件中主鍵列對應的屬性名稱(結果自動存放在該屬性中) 區分大小寫的 -->
<insert id="insertUser" parameterType="cn.jq.mybatis.model.User" useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
insert into t_user
(username,pazzword,state,reg_date)
values
(#{username},#{pazzword},#{state},#{regDate})
</insert>
提交事務之前可以獲取到自動生成id主鍵的值,若不設定獲取不到
//新增一條記錄
User user2 = new User("李四", "123456", 1, new Date());
int i = userMapper.insertUser(user2);
System.out.println("成功新增"+i+"條資料" + user2.getId()); //成功新增1條資料16
session.commit(); //提交事務
2、oracle 使用序列生成主鍵id
對於不支援自動生成型別的資料庫或可能不支援自動生成主鍵的 JDBC 驅動, 如oracle 使用序列
1)建表 和 建序列
CREATE TABLE t_user (
ID NUMBER NOT NULL,
username varchar(255) NOT NULL,
pazzword varchar(255) NOT NULL,
state NUMBER DEFAULT NULL,
reg_date DATE DEFAULT NULL,
PRIMARY KEY (ID)
);
CREATE SEQUENCE seq_userid
START WITH 1
INCREMENT BY 1
MAXVALUE 999999
NOCYCLE
NOCACHE ;
2)sql對映檔案
注意: 要把全域性對映檔案的連線環境切換為 oracle , 引入 oracle 依賴
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.1-atlassian-hosted</version>
</dependency>
<environments default="oracle">
<insert id="insertUser" parameterType="cn.jq.mybatis.model.User">
<!-- 1.先將序列中的值查詢出來 存放在model物件中 新增語句中直接使用該model的屬性即可
order - before 該語句在新增語句之前執行
keyProperty - 查詢結果存放在model物件中的那個屬性中(insert中直接使用屬性即可)
oracle資料庫中 允許為null的列 引數中可設定jdbcType
jdbcType的型別在org.apache.ibatis.type.JdbcType列舉中定義的
-->
<selectKey order="BEFORE" keyProperty="id" resultType="int">
select seq_userid.nextval id from dual
</selectKey>
insert into t_user
(id,username,pazzword,state,reg_date)
values
(#{id},#{username},#{pazzword},#{state,jdbcType=NUMERIC},#{regDate,jdbcType=DATE})
</insert>
3)測試類
User user2 = new User("李四", "123456", 1, new Date());
int i = userMapper.insertUser(user2);
System.out.println("成功新增"+i+"條資料" + user2.getId()); //成功新增1條資料1
session.commit(); //提交事務