mybatis的入門需要掌握以下幾點:
1、使用jdbc程序使用原生態的jdbc進行開發存在很多弊端,優點是執行效率高,mybatis彌補了jdbc的缺陷。
2、mybatis的架構(重點)。
3、mybatis的入門程序(重點)。
實現數據的查詢、添加、修改、刪除
4、mybatis開發DAO的兩種方法(重點)
原始的DAO開發方式(DAO接口和DAO實現都需要編寫)
mapper代理方式(只需要編寫DAO接口)
5、輸入映射類型和輸出映射類型
6、動態SQL
mybatis的高級知識主要包括以下幾點:
高級映射查詢(一對一、一對多、多對多)(重點)
查詢緩存
延遲加載
mybatis和Spring整合(重點)
mybatis逆向工程
開發環境(eclipse、MySQL)
創建數據庫
創建數據庫mybatis
新建表結構:
sql_table.sql
[sql] view plain copy
- *
- SQLyog v10.2
- MySQL - 5.1.72-community : Database - mybatis
- *********************************************************************
- */
- /*!40101 SET NAMES utf8 */;
- /*!40101 SET SQL_MODE=''*/;
- /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
- /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
- /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
- /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
- /*Table structure for table `items` */
- CREATE TABLE `items` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(32) NOT NULL COMMENT '商品名稱',
- `price` float(10,1) NOT NULL COMMENT '商品定價',
- `detail` text COMMENT '商品描述',
- `pic` varchar(64) DEFAULT NULL COMMENT '商品圖片',
- `createtime` datetime NOT NULL COMMENT '生產日期',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
- /*Table structure for table `orderdetail` */
- CREATE TABLE `orderdetail` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `orders_id` int(11) NOT NULL COMMENT '訂單id',
- `items_id` int(11) NOT NULL COMMENT '商品id',
- `items_num` int(11) DEFAULT NULL COMMENT '商品購買數量',
- PRIMARY KEY (`id`),
- KEY `FK_orderdetail_1` (`orders_id`),
- KEY `FK_orderdetail_2` (`items_id`),
- CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
- CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
- ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
- /*Table structure for table `orders` */
- CREATE TABLE `orders` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `user_id` int(11) NOT NULL COMMENT '下單用戶id',
- `number` varchar(32) NOT NULL COMMENT '訂單號',
- `createtime` datetime NOT NULL COMMENT '創建訂單時間',
- `note` varchar(100) DEFAULT NULL COMMENT '備註',
- PRIMARY KEY (`id`),
- KEY `FK_orders_1` (`user_id`),
- CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
- ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
- /*Table structure for table `user` */
- CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `username` varchar(32) NOT NULL COMMENT '用戶名稱',
- `birthday` date DEFAULT NULL COMMENT '生日',
- `sex` char(1) DEFAULT NULL COMMENT '性別',
- `address` varchar(256) DEFAULT NULL COMMENT '地址',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
- /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
- /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
- /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
- /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
創建數據
sql_data.sql
[sql] view plain copy
- /*
- SQLyog v10.2
- MySQL - 5.1.72-community : Database - mybatis
- *********************************************************************
- */
- /*!40101 SET NAMES utf8 */;
- /*!40101 SET SQL_MODE=''*/;
- /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
- /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
- /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
- /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
- /*Data for the table `items` */
- insert into `items`(`id`,`name`,`price`,`detail`,`pic`,`createtime`) values (1,'臺式機',3000.0,'該電腦質量非常好!!!!',NULL,'2015-02-03 13:22:53'),(2,'筆記本',6000.0,'筆記本性能好,質量好!!!!!',NULL,'2015-02-09 13:22:57'),(3,'揹包',200.0,'名牌揹包,容量大質量好!!!!',NULL,'2015-02-06 13:23:02');
- /*Data for the table `orderdetail` */
- insert into `orderdetail`(`id`,`orders_id`,`items_id`,`items_num`) values (1,3,1,1),(2,3,2,3),(3,4,3,4),(4,4,2,3);
- /*Data for the table `orders` */
- insert into `orders`(`id`,`user_id`,`number`,`createtime`,`note`) values (3,1,'1000010','2015-02-04 13:22:35',NULL),(4,1,'1000011','2015-02-03 13:22:41',NULL),(5,10,'1000012','2015-02-12 16:13:23',NULL);
- /*Data for the table `user` */
- insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'王五',NULL,'2',NULL),(10,'張三','2014-07-10','1','北京市'),(16,'張小明',NULL,'1','河南鄭州'),(22,'陳小明',NULL,'1','河南鄭州'),(24,'張三丰',NULL,'1','河南鄭州'),(25,'陳小明',NULL,'1','河南鄭州'),(26,'王五',NULL,NULL,NULL);
- /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
- /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
- /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
- /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
jdbc編程中的問題
企業開發中,根據項目大小、特點進行技術選型,jdbc操作數據庫時效率時很高的,jdbc也是結束選型的參考
jdbc程序
需要數據庫驅動包
上邊是MySQL的驅動,下邊是oracle的驅動
參考下邊一段程序
[java] view plain copy
- package test.lx.mybatis.jdbc;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- /**
- * jdbc的測試程序
- *
- * @author lx
- *
- */
- public class JdbcTest {
- public static void main(String[] args) {
- Connection connection = null;
- //PreparedStatement是預編譯的Statement,通過Statement發起數據庫的操作
- //PreparedStatement防止sql注入,執行數據庫效率高
- PreparedStatement preparedStatement = null;
- ResultSet resultSet = null;
- try {
- //加載數據庫驅動
- Class.forName("com.mysql.jdbc.Driver");
- //通過驅動管理類獲取數據庫鏈接
- connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
- //定義sql語句 ?表示佔位符
- String sql = "select * from user where username = ?" ;
- //獲取預處理statement
- preparedStatement = connection.prepareStatement(sql);
- //設置參數,第一個參數爲sql語句中參數的序號(從1開始),第二個參數爲設置的參數值
- preparedStatement.setString(1, "王五");
- //向數據庫發出sql執行查詢,查詢出結果集
- resultSet = preparedStatement.executeQuery();
- //遍歷查詢結果集
- while(resultSet.next()){
- System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- //釋放資源
- if(resultSet!=null){
- try {
- resultSet.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if(preparedStatement!=null){
- try {
- preparedStatement.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if(connection!=null){
- try {
- connection.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- }
jdbc問題總結
1、數據庫連接頻繁的創建和關閉,缺點浪費數據庫的資源,影響操作效率
設想:使用數據庫連接池
2、SQL語句是硬編碼,如果需求變更需要修改SQL,就需要修改Java代碼,需要重新編譯,系統不易維護。
設想:將SQL語句統一配置在文件中,修改SQL不需要修改Java代碼
3、通過PreparedStatement向佔位符設置參數,存在硬編碼(參數位置,參數)問題。系統不易維護。
設想:將SQL中的佔位符以及對應的參數類型配置在配置文件中,能夠自動輸入映射
4、遍歷查詢結果集中存在硬編碼(列名)
設想:自動進行SQL查詢結果向Java對象的映射(輸出映射)
mybatis架構(重點)
mybatis介紹:
- mybatis本是Apache的一個開源項目ibatis,2010年這個項目由Apache software foundation遷移到了Google code,並且改名爲mybatis,實質上mybatis對ibatis進行了一些改進。目前mybatis在GitHub上託管。git(分佈式版本控制,當前比較流行)
- mybatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注SQL本身,而不需要花費精力去處理例如註冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
- mybatis通過xml或註解的方式將要執行的各種statement( statement、PreparedStatement、CallableStatement)配置起來,並通過Java對象和Statement中的SQL進行映射生成最終執行的SQL語句,最後由mybatis框架執行SQL並將結果映射成Java對象並返回。
mybatis架構
mybatis入門程序
需求
實現用戶查詢:
根據用戶的id查詢用戶的信息(單條記錄)
根據用戶名模糊查詢用戶信息(多條記錄)
用戶添加、用戶修改、用刪除
導入jar包
從mybatis官網下載地址是: https://github.com/mybatis/mybatis-3/releases
mybatis-3.2.7.pdf —操作手冊
mybatis-3.2.7.jar— 核心jar
lib—依賴jar包
工程結構
log4j.properties(公用文件)
建議開發環境中要使用debug
[plain] view plain copy
- # Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug
- log4j.rootLogger=DEBUG, stdout
- # Console output...
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml(公用文件)
通過SqlMapConfig.xml加載mybatis運行環境
[html] view plain 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>
- <!-- 和Spring整合後environments配置將廢除 -->
- <environments default="development">
- <environment id="development">
- <!-- 使用jdbc事務管理 -->
- <transactionManager type="JDBC" />
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver" />
- <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
- <property name="username" value="root" />
- <property name="password" value="root" />
- </dataSource>
- </environment>
- </environments>
- <!-- 加載mapper文件 -->
- <mappers>
- <mapper resource="sqlmap/User.xml" />
- </mappers>
- </configuration>
根據id查詢用戶
pojo (User.java)
[java] view plain copy
- public class User {
- private int id;
- private String username; // 用戶姓名
- private String sex; // 性別
- private Date birthday; // 生日
- private String address; // 地址
- // 添加對應的setter和getter方法
- ......
- }
User.xml (重點)
建議命名規則:表名+mapper.xml
早期ibatis命名規則:表名.xml
[html] view plain copy
- <?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命名空間,爲了對SQL語句進行隔離,方便管理,mapper可開發dao方式,使用namespace有特殊作用
- mapper代理開發時將namespace指定爲mapper接口的全限定名 -->
- <mapper namespace="test">
- <!-- 在mapper.xml文件中配置很多的SQL語句,執行每個SQL語句時,封裝爲MappedStatement對象
- mapper.xml以statement爲單位管理SQL語句
- -->
- <!-- 根據id查詢用戶信息 -->
- <!--
- id: 唯一標識一個statement
- #{}:表示一個佔位符,如果#{} 中傳入簡單類型的參數,#{}中的名稱隨意
- parameterType: 輸入參數的類型,通過#{}接收parameterType輸入的參數
- resultType:輸出結果類型,指定單條記錄映射的pojo類型
- -->
- <select id="findUserById" parameterType="int" resultType="test.lx.mybatis.po.User">
- SELECT * FROM USER WHERE id=#{id};
- </select>
- </mapper>
編碼
創建SqlSessionFactory
[java] view plain copy
- // 會話工廠
- private SqlSessionFactory sqlSessionFactory;
- // 創建工廠
- @Before
- public void init() throws IOException {
- // 配置文件(SqlMapConfig.xml)
- String resource = "SqlMapConfig.xml";
- // 加載配置文件到輸入 流
- InputStream inputStream = Resources.getResourceAsStream(resource);
- // 創建會話工廠
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- }
- // 測試根據id查詢用戶(得到單條記錄)
- @Test
- public void testFindUserById() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 通過sqlSession操作數據庫
- // 第一個參數:statement的位置,等於namespace+statement的id
- // 第二個參數:傳入的參數
- User user = null;
- try {
- user = sqlSession.selectOne("test.findUserById", 1);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- System.out.println(user);
- }
根據用戶名稱模糊查詢用戶信息
根據用戶名稱模糊查詢用戶信息可能返回多條記錄。
User.xml
[html] view plain copy
- <!-- 根據用戶名稱查詢用戶信息,可能返回多條
- ${}:表示SQL的拼接,通過${}接收參數,將參數的內容不加任何修飾的拼接在SQL中
- -->
- <select id="findUserByName" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like '%${value}%'
- </select>
- <select id="findUserByName2" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like #{username}
- </select>
編碼
[java] view plain copy
- // 測試根據名稱模糊查詢用戶(可能得到多條記錄)
- @Test
- public void testFindUserByName() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 通過sqlSession操作數據庫
- // 第一個參數:statement的位置,等於namespace+statement的id
- // 第二個參數:傳入的參數
- List<User> list = null;
- try {
- //list = sqlSession.selectList("test.findUserByName", "小明");
- list = sqlSession.selectList("test.findUserByName2", "%小明%");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- System.out.println(list.size());
- }
mybatis開發過程小結
1.編寫SqlMapConfig.xml
2.編寫mapper.xml(定義了statement)
3.編程通過配置文件創建SqlSessionFactory
4.通過SqlSessionFactory獲取SqlSession
5.通過SqlSession操作數據庫(如果執行修改、添加、刪除需要調用SqlSession.commit())
6.SqlSession使用完後後要關閉
用戶添加
向用戶表中添加一條數據記錄
User.xml
[html] view plain copy
- <!-- 添加用戶
- parameterType:輸入參數的類型,User對象包括username,birthday,sex,address
- #{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
- #{username}表示從parameterType中獲取pojo的屬性值
- -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
編碼
[java] view plain copy
- @Test
- public void testInsertUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- //創建插入數據對象
- User user = new User();
- user.setUsername("一蓑煙雨");
- user.setAddress("河南周口");
- user.setBirthday(new Date());
- user.setSex("1");
- try {
- sqlSession.insert("test.insertUser", user);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- }
測試結果如下
主鍵返回
需求:user對象插入到數據庫後,新紀錄的主鍵要通過user對象返回,通過user獲取主鍵值。
解決思路:
通過LAST_INSERT_ID()獲取剛插入記錄的自增主鍵值,在insert語句執行後,執行select LAST_INSERT_ID()就可以獲取自增主鍵。注意:此語句必須和INSERT語句一塊使用並且要在插入後執行。
修改User.xml
[html] view plain copy
- <!-- 添加用戶
- parameterType:輸入參數的類型,User對象包括username,birthday,sex,address
- #{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
- #{username}表示從parameterType中獲取pojo的屬性值
- <selectKey>:用於進行主鍵返回,定義了主鍵值的SQL
- order:設置selectKey標籤中SQL的執行順序,相對於insert語句而言
- keyProperty: 將主鍵設置到哪個屬性上
- resultType:select LAST_INSERT_ID()的結果類型
- -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="AFTER" resultType="int">
- select LAST_INSERT_ID()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
使用MySQL的uuid機制生成主鍵:
使用uuid生成主鍵的好處是不考慮數據庫移植後的主鍵衝突問題
實現思路:先查詢uuid得到主鍵,將主鍵設置到user對象中,將user插入到數據庫中
[html] view plain copy
- <!-- mysql的uuid()函數生成主鍵 -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="string">
- select uuid()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
如何實現oracle數據庫的主鍵返回?
oracle沒有自增主鍵機制,使用序列完成主鍵生成
實現思路:先查詢序列得到主鍵,將主鍵設置到user對象中,將user對象插入數據庫
[html] view plain copy
- <!-- oracle
- 在執行insert之前執行select 序列.nextval() from dual取出序列最大值,將值設置到user對象的id屬性中
- -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="int">
- select 序列.nextval() from dual
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
用戶刪除和更新
User.xml
[html] view plain copy
- <!-- 用戶刪除 -->
- <delete id="deleteUser" parameterType="int">
- delete from user where id=#{id}
- </delete>
- <!-- 用戶更新
- 要求:傳入的user對象包括id屬性值
- -->
- <update id="updateUser" parameterType="test.lx.mybatis.po.User">
- update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
- </update>
編碼
[java] view plain copy
- // 測試刪除用戶
- @Test
- public void testDeleteUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- try {
- sqlSession.delete("test.deleteUser", 28);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- }
- // 測試根據id更新用戶(得到單條記錄)
- @Test
- public void testUpdateUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- //創建更新數據庫對象,要求必須包括id
- User user= new User();
- user.setId(28);
- user.setUsername("任平生");
- //凡是沒有設置的屬性都被當成了NULL進行賦值
- //user.setBirthday(new Date());
- user.setSex("1");
- try {
- sqlSession.delete("test.updateUser", user);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- }
Mybatis解決jdbc編程中的問題
1.數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響性能,如果使用數據庫連接池可以解決此問題。
解決:在SqlMapConfig.xml中配置數據連接池,使用連接池管理數據庫連接。
2.SQL語句寫在代碼中造成代碼不易維護,實際應用SQL變化可能較大,SQL變動需要改變Java代碼。
解決:將SQL語句配置在XXXXMapper.xml文件中與Java代碼分離。
3.向SQL語句中傳參數麻煩,因爲SQL語句的where條件不一定,可能多也可能少,佔位符和參數要一一對應。
解決:Mybatis自動將Java對象映射至SQL語句,通過statement中的parameterType定義輸入參數的類型。
4.對結果集解析麻煩,SQL變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。
解決:Mybatis自動將SQL執行結果映射至Java對象,通過statement中的resultType定義輸出結果的類型
Mybatis與Hibernate的重要區別
企業開發進行選型,考慮mybatis和Hibernate適用場景。
Mybatis:入門簡單,程序容易上手開發,節省開發成本。Mybatis需要程序員自己編寫SQL語句,是一個不完全的ORM框架,對SQL修改和優化非常容易實現。Mybatis適合開發需求變更頻繁的系統,比如:互聯網項目。
Hibernate:入門門檻高,如果使用Hibernate寫出高性能的程序不容易實現。Hibernate不用寫SQL語句,是一個完全的ORM框架。Hibernate適合需求固定,對象數據模型穩定,中小型項目,比如:企業OA系統。
總之,企業在技術選型時根據項目實際情況,以降低成本和提高系統可維護性爲出發點進行技術選型。
總結
SqlMapConfig.xml
是mybatis全局配置文件,只有一個,名稱不固定,主要mapper.xml,mapper.xml中配置SQL語句。
mapper.xml
mapper.xml是以statement爲單位進行配置。(把一個SQL稱爲一個statement),statement中配置SQL語句、parameterType輸入參數類型(完成輸入映射)、resultType輸出結果類型(完成輸出映射)。
還提供了parameterMap配置輸入參數類型(已過期,不推薦使用)
還提供了resultMap配置輸出結果類型(完成輸出映射)。
佔位符#{}
#{}表示一個佔位符嗎,向佔位符輸入參數,mybatis自動進行Java類型和jdbc類型的轉換。程序員不需要考慮參數的類型,比如傳入字符串,mybatis最終拼接好的SQL就是參數兩邊加上單引號。#{} 接收pojo數據,可以使用OGNL解析出pojo的屬性值。
拼接符${}
表示SQL的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在SQL中。${}也可以接收pojo的數據,可以使用OGNL解析出pojo的屬性值。
缺點:不能防止SQL注入。
selectOne和selectList
selectOne用於查詢單條記錄,不能用於查詢多條記錄,否則會拋出異常。而selectList用戶查詢多條記錄,也可用於查詢單條記錄。
mybatis開發DAO的方法
SqlSession的作用範圍
SqlSessionFactoryBuilder: 是以工具類的方式來使用,需要創建SqlSessionFactory時就new一個SqlSessionFactoryBuilder。
SqlSessionFactory:正常開發時,以單例方式管理SqlSessionFactory,整個系統運行過程中SqlSessionFactory只有一個實例,將來和Spring整合後由Spring以單例模式管理SqlSessionFactory。
SqlSession: SqlSession是一個面向用戶(程序員)的接口,程序員調用SqlSession的 接口方法進行操作數據庫
問題:SqlSession是否能以單例方式使用?
由於SqlSession是線程不安全的,所以SqlSession最佳應用範圍是在方法體內,在方法體內定義局部變量使用SqlSession。
原始DAO的開發方式
程序員需要編寫DAO接口和DAO的實現類
DAO接口
[java] view plain copy
- public interface UserDao {
- // 根據id查詢用戶信息
- public User findUserById(int id) throws Exception;
- }
DAO接口的實現
[java] view plain copy
- public class UserDaoImpl implements UserDao {
- private SqlSessionFactory sqlSessionFactory;
- //將SqlSessionFactory注入
- public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
- this.sqlSessionFactory = sqlSessionFactory;
- }
- public User findUserById(int id) throws Exception {
- //創建SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //根據id查詢用戶信息
- User user = sqlSession.selectOne("test.findUserById", id);
- sqlSession.close();
- return user;
- }
- }
測試代碼
[java] view plain copy
- public class UserDaoImplTest {
- // 會話工廠
- private SqlSessionFactory sqlSessionFactory;
- //創建工廠
- @Before
- public void init() throws IOException{
- //配置文件(SqlMapConfig.xml)
- String resource = "SqlMapConfig.xml";
- //加載配置文件到輸入流
- InputStream inputStream = Resources.getResourceAsStream(resource);
- //創建會話工廠
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- }
- @Test
- public void testFindUserById() throws Exception{
- UserDao userDao = new UserDaoImpl(sqlSessionFactory);
- User user = userDao.findUserById(1);
- System.out.println(user);
- }
- }
mapper代理方式
對於mapper代理的方式,程序員只需要寫DAO接口,DAO接口實現對象由mybatis自動生成代理對象。本身DAO在三層架構中就是一個通用的接口。
原始DAO開發方式的問題
- DAO的實現類中存在重複代碼,整個mybatis操作的過程代碼模板重複(先創建SqlSession、調用SqlSession的方法、關閉SqlSession)
- DAO的實現類中存在硬編碼,調用SqlSession方法時將statement的id硬編碼。
mapper開發規範
要想讓mybatis自動創建DAO接口實現類的代理對象,必須遵循一些規則:
1.mapper.xml中namespace指定爲mapper接口的全限定名。
[html] view plain copy
- <?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命名空間,爲了對SQL語句進行隔離,方便管理,mapper可開發dao方式,使用namespace有特殊作用
- mapper代理開發時將namespace指定爲mapper接口的全限定名 -->
- <mapper namespace="test.lx.mybatis.mapper.UserMapper">
- ......
此步驟目的:通過mapper.xml和mapper.java進行關聯
2.mapper.xml中statement的id就是mapper.java中的方法名。
3.mapper.xml中statement的parameterType和mapper.java中方法輸入參數類型一致。
4.mapper.xml中statement的resultType和mapper.java中方法返回值一致。
mapper.xml(映射文件)
mapper映射文件的命名方式建議: 表名Mapper.xml
namespace指定爲mapper接口的全限定名
[html] view plain copy
- <!-- 根據id查詢用戶信息 -->
- <!--
- id: 唯一標識一個statement
- #{}:表示一個佔位符,如果#{} 中傳入簡單類型的參數,#{}中的名稱隨意
- parameterType: 輸入參數的類型,通過#{}接收parameterType輸入的參數
- resultType:輸出結果類型,不管返回是多條還是單條,指定單條記錄映射的pojo類型
- -->
- <select id="findUserById" parameterType="int" resultType="test.lx.mybatis.po.User">
- SELECT * FROM USER WHERE id=#{id};
- </select>
mapper接口
mybatis提出了mapper接口,相當於DAO接口
mapper接口的命名方式建議: 表名Mapper
[html] view plain copy
- public interface UserMapper {
- //根據用戶id查詢用戶信息
- public User findUserById(int id) throws Exception;
- }
將mapper.xml在SqlMapConfig.xml中加載
[html] view plain copy
- <!-- 加載mapper文件 -->
- <mappers>
- <mapper resource="sqlmap/User.xml" />
- <mapper resource="test/lx/mybatis/mapper/UserMapper.xml"/>
- </mappers>
mapper接口返回單個對象和集合對象
不管查詢記錄是單條還是多條,在statement中resultType定義一致,都是單條記錄映射的pojo類型。
mapper接口方法返回值,如果是返回的單個對象,返回值類型是pojo類型,生成的代理對象內部通過selectOne獲取記錄,如果返回值類型是集合對象,生成的代理對象內部通過selectList獲取記錄。
[java] view plain copy
- //根據用戶id查詢用戶信息
- public User findUserById(int id) throws Exception;
- //根據用戶姓名查詢用戶信息
- public List<User> findUserByName(String username) throws Exception;
問題
返回值問題
如果方法調用的statement,返回的是多條記錄,而mapper.java方法的返回值爲pojo,此時代理對象通過selectOne調用,由於返回多條記錄,所以報錯:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
輸入參數的問題
使用mapper代理的方式開發,mapper接口方法輸入參數只有一個,可擴展性是否很差?
擴展性沒有任何問題,因爲DAO層就是通用的,可以通過擴展pojo(定義pojo包裝類型)將不同的參數(可以是pojo也可以是簡單類型)傳入進去。
SqlMapConfig.xml
SqlMapConfig.xml中配置的內容和順序如下:
properties(屬性)
settings(全局配置參數)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境集合屬性對象)
environment(環境子屬性對象)
transactionManager(事務管理器)
dataSource(數據源)
mappers(映射器)
properties屬性定義
可以把一些通用的屬性值配置在屬性文件中,加載到mybatis運行環境內,比如:創建db.properties配置數據庫連接參數。
[html] view plain copy
- <!-- 屬性定義
- 加載一個properties文件
- 在properties標籤中配置屬性值
- -->
- <properties resource="db.properties">
- <!-- <property name="" value=""/> -->
- </properties>
- <!-- 和Spring整合後environments配置將廢除 -->
- <environments default="development">
- <environment id="development">
- <!-- 使用jdbc事務管理 -->
- <transactionManager type="JDBC" />
- <dataSource type="POOLED">
- <property name="driver" value="${jdbc.driver}" />
- <property name="url" value="${jdbc.url}" />
- <property name="username" value="${jdbc.username}" />
- <property name="password" value="${jdbc.password}" />
- </dataSource>
- </environment>
- </environments>
注意:Mybatis將按照下面的順序加載屬性:
- 在properties元素體內定義的屬性首先被讀取。
- 然後會讀取properties元素中resource或url加載的屬性,它會覆蓋已經讀取的同名屬性。
- 最後讀取parameterType傳遞的屬性,它會覆蓋已經讀取的同名屬性。
建議使用properties,不要在properties中定義屬性,只引用定義的properties文件中的屬性,並且properties中定義的key要有一些特殊的規則。
settings全局參數配置
mybatis運行時可以調整一些全局參數,根據使用需求進行參數配置。注意:需要小心配置,配置的參數會影響mybatis的執行。
ibatis的全局配置參數中包括很多的性能參數(最大線程數,最大等待時間...),通過調整這些參數使ibatis達到高性能的運行,mybatis沒有這些性能參數,由mybatis自行調節。
mybatis中全局參數配置示例如下:
[html] view plain copy
- <settings>
- <setting name="cacheEnabled" value="true"/>
- </settings>
還有許多全局參數,根據需求進行配置,如下表所示:
Setting(設置) Description(描述) Valid Values(驗證值組)Default(默認值)
- cacheEnabled 在全局範圍內啓用或禁用緩存配置任何映射器在此配置下。取值範圍(true | false),默認值爲TRUE
- lazyLoadingEnabled 在全局範圍內啓用或禁用延遲加載。禁用時,所有協會將熱加載。取值範圍(true | false),默認值爲TRUE
- aggressiveLazyLoading 啓用時,有延遲加載屬性的對象將被完全加載後調用懶惰的任何屬性。否則,每一個屬性是按需加載。取值範圍(true | false),默認值爲TRUE
- multipleResultSetsEnabled 允許或不允許從一個單獨的語句(需要兼容的驅動程序)要返回多個結果集。取值範圍(true | false)默認值爲TRUE。
- useColumnLabel 使用列標籤,而不是列名。在這方面,不同的驅動有不同的行爲。參考驅動文檔或測試兩種方法來決定你的驅動程序的行爲如何。取值範圍(true | false),默認值爲TRUE。
- useGeneratedKeys 允許JDBC支持生成的密鑰。兼容的驅動程序是必需的。此設置強制生成的鍵被使用,如果設置爲true,一些驅動會不兼容性,但仍然可以工作。取值範圍(true | false),默認值爲FALSE。
- autoMappingBehavior 指定MyBatis的應如何自動映射列到字段/屬性。NONE自動映射。 PARTIAL只會自動映射結果沒有嵌套結果映射定義裏面。 FULL會自動映射的結果映射任何複雜的(包含嵌套或其他)。取值範圍(NONE, PARTIAL, FULL),默認值爲PARTIAL。
- defaultExecutorType 配置默認執行器。SIMPLE執行器確實沒有什麼特別的。 REUSE執行器重用準備好的語句。 BATCH執行器重用語句和批處理更新。取值範圍(SIMPLE REUSE BATCH),默認值爲SIMPLE。
- defaultStatementTimeout 設置驅動程序等待一個數據庫響應的秒數。任意整型不允許爲空(Any positive integer Not Set (null))。
- safeRowBoundsEnabled 允許使用嵌套的語句RowBounds。取值範圍(true | false),默認值爲FALSE。
- mapUnderscoreToCamelCase 從經典的數據庫列名A_COLUMN啓用自動映射到駱駝標識的經典的Java屬性名aColumn。取值範圍(true | false),默認值爲FALSE。
- localCacheScope MyBatis的使用本地緩存,以防止循環引用,並加快反覆嵌套查詢。默認情況下(SESSION)會話期間執行的所有查詢緩存。如果localCacheScope=STATMENT本地會話將被用於語句的執行,只是沒有將數據共享之間的兩個不同的調用相同的SqlSession。取值範圍(SESSION | STATEMENT),默認值爲SESSION。
- dbcTypeForNull 指定爲空值時,沒有特定的JDBC類型的參數的JDBC類型。有些驅動需要指定列的JDBC類型,但其他像NULL,VARCHAR或OTHER的工作與通用值。JdbcType enumeration. Most common are: NULL, VARCHAR and OTHEROTHER
- lazyLoadTriggerMethods 指定觸發延遲加載的對象的方法。A method name list separated by commas equals,clone,hashCode,toString
- defaultScriptingLanguage 指定所使用的語言默認爲動態SQL生成。A type alias or fully qualified class name.org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
- callSettersOnNulls 指定如果setter方法或地圖的put方法時,將調用檢索到的值是null。它是有用的,當你依靠Map.keySet()或null初始化。注意原語(如整型,布爾等)不會被設置爲null。取值範圍(true | false)FALSE
- logPrefix 指定的前綴字串,MyBatis將會增加記錄器的名稱。Any StringNot set
- logImpl 指定MyBatis的日誌實現使用。如果此設置是不存在的記錄的實施將自動查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGINGNot set
- proxyFactory 指定代理工具,MyBatis將會使用創建懶加載能力的對象。CGLIB | JAVASSIST
typeAliases別名(常用)
mybatis提供的別名
別名 |
映射的類型 |
_byte |
byte |
_long |
long |
_short |
short |
_int |
int |
_integer |
int |
_double |
double |
_float |
float |
_boolean |
boolean |
string |
String |
byte |
Byte |
long |
Long |
short |
Short |
int |
Integer |
integer |
Integer |
double |
Double |
float |
Float |
boolean |
Boolean |
date |
Date |
decimal |
BigDecimal |
bigdecimal |
BigDecimal |
自定義別名
[html] view plain copy
- <!-- 定義別名 -->
- <typeAliases>
- <!--
- 單個別名定義
- alias:別名, type:別名映射類型
- <typeAlias type="test.lx.mybatis.po.User" alias="user"/>
- -->
- <!-- 批量別名定義
- 指定包路徑,自動掃描包內的pojo,定義別名,別名默認爲類名(首字母小寫或大寫)
- -->
- <package name="test.lx.mybatis.po"/>
- </typeAliases>
使用別名
在parameterType、resultType中使用別名:
[html] view plain copy
- <!-- 根據id查詢用戶信息 -->
- <!--
- id: 唯一標識一個statement
- #{}:表示一個佔位符,如果#{} 中傳入簡單類型的參數,#{}中的名稱隨意
- parameterType: 輸入參數的類型,通過#{}接收parameterType輸入的參數
- resultType:輸出結果類型,不管返回是多條還是單條,指定單條記錄映射的pojo類型
- -->
- <select id="findUserById" parameterType="int" resultType="user">
- SELECT * FROM USER WHERE id=#{id};
- </select>
typeHandlers
類型處理器將Java類型和jdbc類型進行映射。
mybatis默認提供很多類型處理器,一般情況下足夠使用。
mappers
[html] view plain copy
- <!-- 加載mapper映射
- 如果和Spring整合後,可以使用整合包中的mapper掃描器,到那時此處的mapper就不用配置了
- -->
- <mappers>
- <!-- 通過resource映入mapper的映射文件 -->
- <mapper resource="sqlmap/User.xml" />
- <!-- <mapper resource="test/lx/mybatis/mapper/UserMapper.xml"/> -->
- <!-- 通過class引用mapper接口
- class:配置mapper接口的全限定名
- 要求:需要mapper.xml和mapper.java同名並且在同一目錄中
- -->
- <!-- <mapper class="test.lx.mybatis.mapper.UserMapper"/> -->
- <!-- 批量mapper配置
- 通過package進行自動掃描包下邊的mapper接口
- 要求:需要mapper.xml和mapper.java同名並在同一目錄中
- -->
- <package name="test.lx.mybatis.mapper"/>
- </mappers>
輸入和輸出映射
通過parameterType完成輸入映射,通過resultType和resultMap完成輸出映射。
parameterType傳遞pojo包裝對象
可以自定義pojo包裝類型擴展mapper接口輸入參數的內容。
需求:自定義查詢條件查詢用戶信息,需要向statement輸入查詢條件,查詢條件可以有user信息,商品信息......
定義包裝類型
[java] view plain copy
- public class UserQueryVo {
- //用戶信息
- private User user;
- //自定義User的擴展對象
- private UserCustom userCustom;
- //提供對應的getter和setter方法
- ......
- }
mapper.xml
[html] view plain copy
- <!-- 自定義查詢條件查詢用戶信息
- parameterType: 指定包裝類型
- %${userCustom.username}%: userCustom是userQueryVo中的屬性,通過OGNL獲取屬性的值
- -->
- <select id="findUserList" parameterType="userQueryVo" resultType="user">
- select * from user where username like '%${userCustom.username}%'
- </select>
mapper.java
[java] view plain copy
- //自定義查詢條件查詢用戶信息
- public List<User> findUserList(UserQueryVo userQueryVo) throws Exception;
測試
[java] view plain copy
- //通過包裝類型查詢用戶信息
- @Test
- public void testFindUserList() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- // 構造查詢條件
- UserQueryVo userQueryVo = new UserQueryVo();
- UserCustom userCustom = new UserCustom();
- userCustom.setUsername("小明");
- userQueryVo.setUserCustom(userCustom);
- List<User> list = userMapper.findUserList(userQueryVo);
- System.out.println(list);
- }
異常
如果parameterType中指定屬性錯誤,會拋出異常,找不到getter方法:org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'userCusto' in class …
注意:如果將來和Spring整合後,不是通過getter方法來獲取獲取屬性值,而是通過反射強讀pojo的屬性值。
resultType
指定輸出結果的類型(pojo、簡單類型、hashmap...),將SQL查詢結果映射爲Java對象。
返回簡單類型
mapper.xml
[html] view plain copy
- <!-- 輸出簡單類型
- 功能:自定義查詢條件,返回查詢記錄個數,通常用於實現查詢分頁
- -->
- <select id="findUserCount" parameterType="userQueryVo" resultType="int">
- select count(*) from user where username like '%${userCustom.username}%'
- </select>
mapper.java
[java] view plain copy
- //查詢用戶返回記錄個數
- public int findUserCount(UserQueryVo userQueryVo) throws Exception;
測試代碼
[java] view plain copy
- //返回查詢記錄總數
- @Test
- public void testFindUserCount() throws Exception{
- SqlSession sqlSession =sqlSessionFactory.openSession();
- //創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- //構建查詢條件
- UserQueryVo userQueryVo = new UserQueryVo();
- UserCustom userCustom = new UserCustom();
- userCustom.setUsername("小明");
- userQueryVo.setUserCustom(userCustom);
- int count = userMapper.findUserCount(userQueryVo);
- System.out.println(count);
- }
注意:如果查詢記錄結果集爲一條記錄且一列 才適合返回簡單類型。
resultMap(入門)
resultType:指定輸出結果的類型(pojo、簡單類型、hashmap),將SQL查詢結果映射爲Java對象。
使用resultType注意:sql查詢的列名要和resultType指定pojo的屬性相同,指定相同,屬性方可映射成功。如果sql查詢的列名要和resultType指定pojo的屬性全部不相同,list中是無法創建pojo對象的。有幾個屬性對應相同,則能給對應相同的屬性賦值。
resultMap:將SQL查詢結果映射爲Java對象。如果SQL查詢列名和最終要映射的pojo的屬性名不一致,使用resultMap將列名和pojo的屬性名做一個映射關係(列名和屬性名映射配置)。
resultMap配置
[html] view plain copy
- <!-- 定義resultMap,列名和屬性名映射配置
- id: mapper.xml中唯一標識
- type: 最終要映射的pojo類型
- -->
- <resultMap id="userListResultMap" type="user" >
- <!-- 列名
- id,username_,birthday_
- id:要映射結果集的唯一標識,稱爲主鍵
- column: 結果集的列名
- property:type指定pojo中的某個屬性
- -->
- <id column="id_" property="id" />
- <!-- result就是普通列的映射配置 -->
- <result column="username_" property="username"/>
- <result column="birthday_" property="birthday"/>
- </resultMap>
使用resultMap
[html] view plain copy
- <!-- 使用resultMap作爲結果映射
- resultMap: 如果引用resultMap的位置和resultMap的定義在同一個mapper.xml中,
- 直接使用resultMap的id,如果不在同一個mapper.xml中,要在引用resultMap的id前邊加namespace
- -->
- <select id="findUserListResultMap" parameterType="userQueryVo" resultMap="userListResultMap">
- select id id_,username username_,birthday birthday_ from user where username like '%${userCustom.username}%'
- </select>
mapper.java
[java] view plain copy
- //查詢用戶,使用resultMap進行映射
- public List<User> findUserListResultMap(UserQueryVo userQueryVo) throws Exception;
動態SQL(重點)
需求
將自定義查詢條件查詢用戶列表和查詢用戶列表總記錄數改爲動態SQL。
if和where
[html] view plain copy
- <!-- where標籤相當於where關鍵字,可以自動除去第一個and -->
- <where>
- <!-- 如果userQueryVo中傳入查詢條件,在進行SQL拼接 -->
- <!-- test中userCustom.username表示從userQueryVo中讀取屬性值 -->
- <if test="userCustom!=null">
- <if test="userCustom.username!=null and userCustom.username.trim().length() > 0">
- and username like '%${userCustom.username.trim()}%'
- </if>
- <if test="userCustom.sex!=null and userCustom.sex!=''">
- and sex = #{userCustom.sex}
- </if>
- <!-- 還可以添加更多的查詢條件 -->
- </if>
- </where>
sql片段
通過sql片段可以將通用的SQL語句抽取出來,單獨定義,在其它的statement中可以引用SQL片段。
即通用的SQL語句,常用的:where條件、查詢列
sql片段的定義
[html] view plain copy
- <!-- 將用戶查詢條件定義爲SQL片段
- 建議對單表的查詢條件單獨抽取成SQL片段,提高公用性
- 注意:不要講where標籤放在SQL片段,因爲where條件中可能有多個SQL片段進行結合
- -->
- <sql id="query_user_where">
- <!-- 如果userQueryVo中傳入查詢條件,在進行SQL拼接 -->
- <!-- test中userCustom.username表示從userQueryVo中讀取屬性值 -->
- <if test="userCustom!=null">
- <if test="userCustom.username!=null and userCustom.username.trim().length() > 0">
- and username like '%${userCustom.username.trim()}%'
- </if>
- <if test="userCustom.sex!=null and userCustom.sex!=''">
- and sex = #{userCustom.sex}
- </if>
- <!-- 還可以添加更多的查詢條件 -->
- </if>
- </sql>
引用sql片段
在查詢用戶數據中引用
[html] view plain copy
- <select id="findUserList" parameterType="userQueryVo" resultType="user">
- select * from user
- <!-- where標籤相當於where關鍵字,可以自動除去第一個and -->
- <where>
- <!-- 引用sql片段,如果sql片段和引用處不在同一個mapper 必須在前邊加namespace. -->
- <include refid="query_user_where"></include>
- <!-- 下邊還有很多其它的條件 -->
- <!-- <include refid="其它的sql片段"></include> -->
- </where>
- </select>
在查詢用戶數據總數量中引用
[html] view plain copy
- <!-- 輸出簡單類型
- 功能:自定義查詢條件,返回查詢記錄個數,通常用於實現查詢分頁
- -->
- <select id="findUserCount" parameterType="userQueryVo" resultType="int">
- select count(*) from user
- <!-- where標籤相當於where關鍵字,可以自動除去第一個and -->
- <where>
- <!-- 引用sql片段,如果sql片段和引用處不在同一個mapper 必須在前邊加namespace. -->
- <include refid="query_user_where"></include>
- <!-- 下邊還有很多其它的條件 -->
- <!-- <include refid="其它的sql片段"></include> -->
- </where>
- </select>
foreach
在statement中通過foreach遍歷parameterType中的集合類型
需求:假設根據多個用戶id查詢用戶信息
在userQueryVo中定義list<Integer> ids;
在UserQueryVo中定義List<Integer> ids存儲多個id
[java] view plain copy
- public class UserQueryVo {
- //用戶信息
- private User user;
- //自定義User的擴展對象
- private UserCustom userCustom;
- //用戶id集合
- private List<Integer> ids;
- //添加對應的setter和getter方法
- ......
- }
修改where語句
使用foreach遍歷list
[html] view plain copy
- <!-- 根據id集合查詢用戶信息 -->
- <!-- 最終拼接的效果:
- SELECT id,username,birthday FROM USER WHERE username LIKE '%小明%' AND id IN (16,22,25)
- collection: pojo中的表示集合的屬性
- open: 開始循環拼接的串
- close: 結束循環拼接的串
- item: 每次循環從集合中取到的對象
- separator: 沒兩次循環中間拼接的串
- -->
- <foreach collection="ids" open=" AND id IN (" close=")" item="id" separator=",">
- #{id}
- </foreach>
- <!--
- SELECT id ,username ,birthday FROM USER WHERE username LIKE '%小明%' AND (id = 16 OR id = 22 OR id = 25)
- <foreach collection="ids" open=" AND id IN (" close=")" item="id" separator=" OR ">
- id=#{id}
- </foreach>
- -->
測試代碼
[java] view plain copy
- //id集合
- List<Integer> ids = new ArrayList<Integer>();
- ids.add(16);
- ids.add(22);
- userQueryVo.setIds(ids);
- List<User> list = userMapper.findUserList(userQueryVo);
最終Demo代碼如下:(GitHub地址:https://github.com/LX1993728/mybatisDemo_1)
UserDao
[java] view plain copy
- package test.lx.mybatis.dao;
- import java.util.List;
- import test.lx.mybatis.po.User;
- /**
- * 用戶DAO
- *
- * @author lx
- *
- */
- public interface UserDao {
- // 根據id查詢用戶信息
- public User findUserById(int id) throws Exception;
- // 根據用戶名稱模糊查詢用戶列表
- public List<User> findUserByUsername(String username) throws Exception;
- // 插入用戶
- public void insertUser(User user) throws Exception;
- }
UserDaoImpl
[java] view plain copy
- package test.lx.mybatis.dao;
- import java.util.List;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import test.lx.mybatis.po.User;
- public class UserDaoImpl implements UserDao {
- private SqlSessionFactory sqlSessionFactory;
- //將SqlSessionFactory注入
- public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
- this.sqlSessionFactory = sqlSessionFactory;
- }
- public User findUserById(int id) throws Exception {
- //創建SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //根據id查詢用戶信息
- User user = sqlSession.selectOne("test.findUserById", id);
- sqlSession.close();
- return user;
- }
- public List<User> findUserByUsername(String username) throws Exception {
- //創建SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- List<User> list = sqlSession.selectList("test.findUserByName", username);
- sqlSession.close();
- return list;
- }
- public void insertUser(User user) throws Exception {
- //創建SqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- sqlSession.insert("test.insertUser", user);
- sqlSession.commit();
- sqlSession.close();
- }
- }
MyBatisFirst
[java] view plain copy
- package test.lx.mybatis.first;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Date;
- import java.util.List;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.junit.Before;
- import org.junit.Test;
- import test.lx.mybatis.po.User;
- /**
- * mybatis入門程序
- *
- * @author lx
- *
- */
- public class MybatisFirst {
- // 會話工廠
- private SqlSessionFactory sqlSessionFactory;
- // 創建工廠
- @Before
- public void init() throws IOException {
- // 配置文件(SqlMapConfig.xml)
- String resource = "SqlMapConfig.xml";
- // 加載配置文件到輸入 流
- InputStream inputStream = Resources.getResourceAsStream(resource);
- // 創建會話工廠
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- }
- // 測試根據id查詢用戶(得到單條記錄)
- @Test
- public void testFindUserById() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 通過sqlSession操作數據庫
- // 第一個參數:statement的位置,等於namespace+statement的id
- // 第二個參數:傳入的參數
- User user = null;
- try {
- user = sqlSession.selectOne("test.findUserById", 1);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- System.out.println(user);
- }
- // 測試根據名稱模糊查詢用戶(可能得到多條記錄)
- @Test
- public void testFindUserByName() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 通過sqlSession操作數據庫
- // 第一個參數:statement的位置,等於namespace+statement的id
- // 第二個參數:傳入的參數
- List<User> list = null;
- try {
- //list = sqlSession.selectList("test.findUserByName", "小明");
- list = sqlSession.selectList("test.findUserByName2", "%小明%");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- System.out.println(list.size());
- }
- // 測試插入用戶
- @Test
- public void testInsertUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- //創建插入數據對象
- User user = new User();
- user.setUsername("一蓑煙雨");
- user.setAddress("河南周口");
- user.setBirthday(new Date());
- user.setSex("1");
- try {
- sqlSession.insert("test.insertUser", user);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- System.out.println(user.getId());
- }
- // 測試刪除用戶
- @Test
- public void testDeleteUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- try {
- sqlSession.delete("test.deleteUser", 28);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- }
- // 測試根據id更新用戶(得到單條記錄)
- @Test
- public void testUpdateUser() {
- // 通過sqlSessionFactory創建sqlSession
- SqlSession sqlSession = sqlSessionFactory.openSession();
- //通過sqlSession操作數據庫
- //創建更新數據庫對象,要求必須包括id
- User user= new User();
- user.setId(28);
- user.setUsername("任平生");
- //凡是沒有設置的屬性都被當成了NULL進行賦值
- //user.setBirthday(new Date());
- user.setSex("1");
- try {
- sqlSession.delete("test.updateUser", user);
- //需要提交事務
- sqlSession.commit();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 關閉sqlSession
- sqlSession.close();
- }
- }
- }
JdbcTest
[java] view plain copy
- package test.lx.mybatis.jdbc;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- /**
- * jdbc的測試程序
- *
- * @author lx
- *
- */
- public class JdbcTest {
- public static void main(String[] args) {
- Connection connection = null;
- //PreparedStatement是預編譯的Statement,通過Statement發起數據庫的操作
- //PreparedStatement防止sql注入,執行數據庫效率高
- PreparedStatement preparedStatement = null;
- ResultSet resultSet = null;
- try {
- //加載數據庫驅動
- Class.forName("com.mysql.jdbc.Driver");
- //通過驅動管理類獲取數據庫鏈接
- connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
- //定義sql語句 ?表示佔位符
- String sql = "select * from user where username = ?" ;
- //獲取預處理statement
- preparedStatement = connection.prepareStatement(sql);
- //設置參數,第一個參數爲sql語句中參數的序號(從1開始),第二個參數爲設置的參數值
- preparedStatement.setString(1, "王五");
- //向數據庫發出sql執行查詢,查詢出結果集
- resultSet = preparedStatement.executeQuery();
- //遍歷查詢結果集
- while(resultSet.next()){
- System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- //釋放資源
- if(resultSet!=null){
- try {
- resultSet.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if(preparedStatement!=null){
- try {
- preparedStatement.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if(connection!=null){
- try {
- connection.close();
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- }
UserMapper.java
[java] view plain copy
- package test.lx.mybatis.mapper;
- import java.util.List;
- import test.lx.mybatis.po.User;
- import test.lx.mybatis.po.UserQueryVo;
- /**
- * 用戶mapper
- *
- * @author lx
- *
- */
- public interface UserMapper {
- // 根據用戶id查詢用戶信息
- public User findUserById(int id) throws Exception;
- // 根據用戶姓名查詢用戶信息
- public List<User> findUserByName(String username) throws Exception;
- // 自定義查詢條件查詢用戶信息
- public List<User> findUserList(UserQueryVo userQueryVo) throws Exception;
- // 查詢用戶,使用resultMap進行映射
- public List<User> findUserListResultMap(UserQueryVo userQueryVo) throws Exception;
- // 查詢用戶返回記錄個數
- public int findUserCount(UserQueryVo userQueryVo) throws Exception;
- // 插入用戶
- public void insertUser(User user) throws Exception;
- // 刪除用戶
- public void deleteUser(int id) throws Exception;
- // 修改用戶
- public void updateUser(User user) throws Exception;
- }
UserMapper.xml
[html] view plain copy
- <?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命名空間,爲了對SQL語句進行隔離,方便管理,mapper可開發dao方式,使用namespace有特殊作用
- mapper代理開發時將namespace指定爲mapper接口的全限定名 -->
- <mapper namespace="test.lx.mybatis.mapper.UserMapper">
- <!-- 在mapper.xml文件中配置很多的SQL語句,執行每個SQL語句時,封裝爲MappedStatement對象
- mapper.xml以statement爲單位管理SQL語句
- -->
- <!-- 將用戶查詢條件定義爲SQL片段
- 建議對單表的查詢條件單獨抽取成SQL片段,提高公用性
- 注意:不要講where標籤放在SQL片段,因爲where條件中可能有多個SQL片段進行結合
- -->
- <sql id="query_user_where">
- <!-- 如果userQueryVo中傳入查詢條件,在進行SQL拼接 -->
- <!-- test中userCustom.username表示從userQueryVo中讀取屬性值 -->
- <if test="userCustom!=null">
- <if test="userCustom.username!=null and userCustom.username.trim().length() > 0">
- and username like '%${userCustom.username.trim()}%'
- </if>
- <if test="userCustom.sex!=null and userCustom.sex!=''">
- and sex = #{userCustom.sex}
- </if>
- <!-- 根據id集合查詢用戶信息 -->
- <!-- 最終拼接的效果:
- SELECT id,username,birthday FROM USER WHERE username LIKE '%小明%' AND id IN (16,22,25)
- collection: pojo中的表示集合的屬性
- open: 開始循環拼接的串
- close: 結束循環拼接的串
- item: 每次循環從集合中取到的對象
- separator: 沒兩次循環中間拼接的串
- -->
- <if test="ids != null and ids.size()>0">
- <foreach collection="ids" open=" AND id IN (" close=")" item="id" separator=",">
- #{id}
- </foreach>
- </if>
- <!--
- SELECT id ,username ,birthday FROM USER WHERE username LIKE '%小明%' AND (id = 16 OR id = 22 OR id = 25)
- <foreach collection="ids" open=" AND id IN (" close=")" item="id" separator=" OR ">
- id=#{id}
- </foreach>
- -->
- <!-- 還可以添加更多的查詢條件 -->
- </if>
- </sql>
- <!-- 定義resultMap,列名和屬性名映射配置
- id: mapper.xml中唯一標識
- type: 最終要映射的pojo類型
- -->
- <resultMap id="userListResultMap" type="user" >
- <!-- 列名
- id,username_,birthday_
- id:要映射結果集的唯一標識,稱爲主鍵
- column: 結果集的列名
- property:type指定pojo中的某個屬性
- -->
- <id column="id_" property="id" />
- <!-- result就是普通列的映射配置 -->
- <result column="username_" property="username"/>
- <result column="birthday_" property="birthday"/>
- </resultMap>
- <!-- 根據id查詢用戶信息 -->
- <!--
- id: 唯一標識一個statement
- #{}:表示一個佔位符,如果#{} 中傳入簡單類型的參數,#{}中的名稱隨意
- parameterType: 輸入參數的類型,通過#{}接收parameterType輸入的參數
- resultType:輸出結果類型,不管返回是多條還是單條,指定單條記錄映射的pojo類型
- -->
- <select id="findUserById" parameterType="int" resultType="user">
- SELECT * FROM USER WHERE id=#{id};
- </select>
- <!-- 根據用戶名稱查詢用戶信息,可能返回多條
- ${}:表示SQL的拼接,通過${}接收參數,將參數的內容不加任何修飾的拼接在SQL中
- -->
- <select id="findUserByName" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like '%${value}%'
- </select>
- <!-- <select id="findUserByName" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like #{username}
- </select> -->
- <!-- 自定義查詢條件查詢用戶信息
- parameterType: 指定包裝類型
- %${userCustom.username}%: userCustom是userQueryVo中的屬性,通過OGNL獲取屬性的值
- -->
- <select id="findUserList" parameterType="userQueryVo" resultType="user">
- select * from user
- <!-- where標籤相當於where關鍵字,可以自動除去第一個and -->
- <where>
- <!-- 引用sql片段,如果sql片段和引用處不在同一個mapper 必須在前邊加namespace. -->
- <include refid="query_user_where"></include>
- <!-- 下邊還有很多其它的條件 -->
- <!-- <include refid="其它的sql片段"></include> -->
- </where>
- </select>
- <!-- 使用resultMap作爲結果映射
- resultMap: 如果引用resultMap的位置和resultMap的定義在同一個mapper.xml中,
- 直接使用resultMap的id,如果不在同一個mapper.xml中,要在引用resultMap的id前邊加namespace
- -->
- <select id="findUserListResultMap" parameterType="userQueryVo" resultMap="userListResultMap">
- select id id_,username username_,birthday birthday_ from user where username like '%${userCustom.username}%'
- </select>
- <!-- 輸出簡單類型
- 功能:自定義查詢條件,返回查詢記錄個數,通常用於實現查詢分頁
- -->
- <select id="findUserCount" parameterType="userQueryVo" resultType="int">
- select count(*) from user
- <!-- where標籤相當於where關鍵字,可以自動除去第一個and -->
- <where>
- <!-- 引用sql片段,如果sql片段和引用處不在同一個mapper 必須在前邊加namespace. -->
- <include refid="query_user_where"></include>
- <!-- 下邊還有很多其它的條件 -->
- <!-- <include refid="其它的sql片段"></include> -->
- </where>
- </select>
- <!-- 添加用戶
- parameterType:輸入參數的類型,User對象包括username,birthday,sex,address
- #{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
- #{username}表示從parameterType中獲取pojo的屬性值
- <selectKey>:用於進行主鍵返回,定義了主鍵值的SQL
- order:設置selectKey標籤中SQL的執行順序,相對於insert語句而言
- keyProperty: 將主鍵設置到哪個屬性上
- resultType:select LAST_INSERT_ID()的結果類型
- -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="AFTER" resultType="int">
- select LAST_INSERT_ID()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
- <!-- mysql的uuid()函數生成主鍵 -->
- <!-- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="string">
- select uuid()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert> -->
- <!-- oracle
- 在執行insert之前執行select 序列.nextval() from dual取出序列最大值,將值設置到user對象的id屬性中
- -->
- <!-- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="int">
- select 序列.nextval() from dual
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert> -->
- <!-- 用戶刪除 -->
- <delete id="deleteUser" parameterType="int">
- delete from user where id=#{id}
- </delete>
- <!-- 用戶更新
- 要求:傳入的user對象包括id屬性值
- -->
- <update id="updateUser" parameterType="test.lx.mybatis.po.User">
- update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
- </update>
- </mapper>
User.java
[java] view plain copy
- package test.lx.mybatis.po;
- import java.util.Date;
- /**
- * 用戶PO類
- *
- * @author lx
- *
- */
- public class User {
- private int id;
- private String username; // 用戶姓名
- private String sex; // 性別
- private Date birthday; // 生日
- private String address; // 地址
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public Date getBirthday() {
- return birthday;
- }
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- @Override
- public String toString() {
- return "User [id=" + id + ", username=" + username + ", sex=" + sex
- + ", birthday=" + birthday + ", address=" + address + "]";
- }
- }
UserCustom
[java] view plain copy
- package test.lx.mybatis.po;
- /**
- * User的擴展類型
- * @author liuxun
- *
- */
- public class UserCustom extends User {
- //添加一些擴展類型
- }
UserQueryVo
[java] view plain copy
- package test.lx.mybatis.po;
- import java.util.List;
- /**
- * 包裝類型,將來在使用時從頁面傳遞到controller、service、mapper
- * @author liuxun
- *
- */
- public class UserQueryVo {
- //用戶信息
- private User user;
- //自定義User的擴展對象
- private UserCustom userCustom;
- //用戶id集合
- private List<Integer> ids;
- public User getUser() {
- return user;
- }
- public void setUser(User user) {
- this.user = user;
- }
- public UserCustom getUserCustom() {
- return userCustom;
- }
- public void setUserCustom(UserCustom userCustom) {
- this.userCustom = userCustom;
- }
- public List<Integer> getIds() {
- return ids;
- }
- public void setIds(List<Integer> ids) {
- this.ids = ids;
- }
- }
User.xml
[html] view plain copy
- <?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命名空間,爲了對SQL語句進行隔離,方便管理,mapper可開發dao方式,使用namespace有特殊作用
- mapper代理開發時將namespace指定爲mapper接口的全限定名 -->
- <mapper namespace="test">
- <!-- 在mapper.xml文件中配置很多的SQL語句,執行每個SQL語句時,封裝爲MappedStatement對象
- mapper.xml以statement爲單位管理SQL語句
- -->
- <!-- 根據id查詢用戶信息 -->
- <!--
- id: 唯一標識一個statement
- #{}:表示一個佔位符,如果#{} 中傳入簡單類型的參數,#{}中的名稱隨意
- parameterType: 輸入參數的類型,通過#{}接收parameterType輸入的參數
- resultType:輸出結果類型,指定單條記錄映射的pojo類型
- -->
- <select id="findUserById" parameterType="int" resultType="test.lx.mybatis.po.User">
- SELECT * FROM USER WHERE id=#{id};
- </select>
- <!-- 根據用戶名稱查詢用戶信息,可能返回多條
- ${}:表示SQL的拼接,通過${}接收參數,將參數的內容不加任何修飾的拼接在SQL中
- -->
- <select id="findUserByName" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like '%${value}%'
- </select>
- <select id="findUserByName2" parameterType="java.lang.String" resultType="test.lx.mybatis.po.User">
- select * from user where username like #{username}
- </select>
- <!-- 添加用戶
- parameterType:輸入參數的類型,User對象包括username,birthday,sex,address
- #{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
- #{username}表示從parameterType中獲取pojo的屬性值
- <selectKey>:用於進行主鍵返回,定義了主鍵值的SQL
- order:設置selectKey標籤中SQL的執行順序,相對於insert語句而言
- keyProperty: 將主鍵設置到哪個屬性上
- resultType:select LAST_INSERT_ID()的結果類型
- -->
- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="AFTER" resultType="int">
- select LAST_INSERT_ID()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert>
- <!-- mysql的uuid()函數生成主鍵 -->
- <!-- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="string">
- select uuid()
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert> -->
- <!-- oracle
- 在執行insert之前執行select 序列.nextval() from dual取出序列最大值,將值設置到user對象的id屬性中
- -->
- <!-- <insert id="insertUser" parameterType="test.lx.mybatis.po.User">
- <selectKey keyProperty="id" order="BEFORE" resultType="int">
- select 序列.nextval() from dual
- </selectKey>
- INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
- </insert> -->
- <!-- 用戶刪除 -->
- <delete id="deleteUser" parameterType="int">
- delete from user where id=#{id}
- </delete>
- <!-- 用戶更新
- 要求:傳入的user對象包括id屬性值
- -->
- <update id="updateUser" parameterType="test.lx.mybatis.po.User">
- update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
- </update>
- </mapper>
db.properties
[plain] view plain copy
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatis
- jdbc.username=root
- jdbc.password=root
log4j.properties
[plain] view plain copy
- # Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug
- log4j.rootLogger=DEBUG, stdout
- # Console output...
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.xml
[html] view plain 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文件
- 在properties標籤中配置屬性值
- -->
- <properties resource="db.properties">
- <!-- <property name="" value=""/> -->
- </properties>
- <settings>
- <setting name="cacheEnabled" value="true"/>
- </settings>
- <!-- 定義別名 -->
- <typeAliases>
- <!--
- 單個別名定義
- alias:別名, type:別名映射類型
- <typeAlias type="test.lx.mybatis.po.User" alias="user"/>
- -->
- <!-- 批量別名定義
- 指定包路徑,自動掃描包內的pojo,定義別名,別名默認爲類名(首字母小寫或大寫)
- -->
- <package name="test.lx.mybatis.po"/>
- </typeAliases>
- <!-- 和Spring整合後environments配置將廢除 -->
- <environments default="development">
- <environment id="development">
- <!-- 使用jdbc事務管理 -->
- <transactionManager type="JDBC" />
- <dataSource type="POOLED">
- <property name="driver" value="${jdbc.driver}" />
- <property name="url" value="${jdbc.url}" />
- <property name="username" value="${jdbc.username}" />
- <property name="password" value="${jdbc.password}" />
- </dataSource>
- </environment>
- </environments>
- <!-- 加載mapper映射
- 如果和Spring整合後,可以使用整合包中的mapper掃描器,到那時此處的mapper就不用配置了
- -->
- <mappers>
- <!-- 通過resource映入mapper的映射文件 -->
- <mapper resource="sqlmap/User.xml" />
- <!-- <mapper resource="test/lx/mybatis/mapper/UserMapper.xml"/> -->
- <!-- 通過class引用mapper接口
- class:配置mapper接口的全限定名
- 要求:需要mapper.xml和mapper.java同名並且在同一目錄中
- -->
- <!-- <mapper class="test.lx.mybatis.mapper.UserMapper"/> -->
- <!-- 批量mapper配置
- 通過package進行自動掃描包下邊的mapper接口
- 要求:需要mapper.xml和mapper.java同名並在同一目錄中
- -->
- <package name="test.lx.mybatis.mapper"/>
- </mappers>
- </configuration>
UserDaoImplTest
[java] view plain copy
- package test.lx.mybatis.dao;
- import java.io.IOException;
- import java.io.InputStream;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.junit.Before;
- import org.junit.Test;
- import test.lx.mybatis.po.User;
- public class UserDaoImplTest {
- // 會話工廠
- private SqlSessionFactory sqlSessionFactory;
- //創建工廠
- @Before
- public void init() throws IOException{
- //配置文件(SqlMapConfig.xml)
- String resource = "SqlMapConfig.xml";
- //加載配置文件到輸入流
- InputStream inputStream = Resources.getResourceAsStream(resource);
- //創建會話工廠
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- }
- @Test
- public void testFindUserById() throws Exception{
- UserDao userDao = new UserDaoImpl(sqlSessionFactory);
- User user = userDao.findUserById(1);
- System.out.println(user);
- }
- }
UserMapperTest.java
[java] view plain copy
- package test.lx.mybatis.mapper;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.junit.Before;
- import org.junit.Test;
- import test.lx.mybatis.po.User;
- import test.lx.mybatis.po.UserCustom;
- import test.lx.mybatis.po.UserQueryVo;
- public class UserMapperTest {
- // 會話工廠
- private SqlSessionFactory sqlSessionFactory;
- // 創建工廠
- @Before
- public void init() throws IOException {
- // 配置文件(SqlMapConfig.xml)
- String resource = "SqlMapConfig.xml";
- // 加載配置文件到輸入流
- InputStream inputStream = Resources.getResourceAsStream(resource);
- // 創建會話工廠
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- }
- @Test
- public void testFindUserById() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- User user = userMapper.findUserById(1);
- System.out.println(user);
- sqlSession.close();
- }
- @Test
- public void testFindUserByUsername() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- List<User> list = userMapper.findUserByName("小明");
- sqlSession.close();
- System.out.println(list);
- }
- @Test
- public void testInsertUser() throws Exception{
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- //插入對象
- User user = new User();
- user.setUsername("一蓑煙雨任平生");
- userMapper.insertUser(user);
- sqlSession.commit();
- sqlSession.close();
- System.out.println(user);
- }
- //通過包裝類型查詢用戶信息
- @Test
- public void testFindUserList() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- // 構造查詢條件
- UserQueryVo userQueryVo = new UserQueryVo();
- UserCustom userCustom = new UserCustom();
- userCustom.setUsername(" 小明");
- userCustom.setSex("1");
- userQueryVo.setUserCustom(userCustom);
- //id集合
- List<Integer> ids = new ArrayList<Integer>();
- ids.add(16);
- ids.add(22);
- userQueryVo.setIds(ids);
- List<User> list = userMapper.findUserList(userQueryVo);
- sqlSession.close();
- System.out.println(list);
- }
- //使用resultMap進行結果映射
- @Test
- public void testFindUserListResultMap() throws Exception {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- // 創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- // 構造查詢條件
- UserQueryVo userQueryVo = new UserQueryVo();
- UserCustom userCustom = new UserCustom();
- userCustom.setUsername("小明");
- userQueryVo.setUserCustom(userCustom);
- List<User> list = userMapper.findUserListResultMap(userQueryVo);
- sqlSession.close();
- System.out.println(list);
- }
- //返回查詢記錄總數
- @Test
- public void testFindUserCount() throws Exception{
- SqlSession sqlSession =sqlSessionFactory.openSession();
- //創建代理對象
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- //構建查詢條件
- UserQueryVo userQueryVo = new UserQueryVo();
- UserCustom userCustom = new UserCustom();
- userCustom.setUsername("小明");
- userQueryVo.setUserCustom(userCustom);
- int count = userMapper.findUserCount(userQueryVo);
- sqlSession.close();
- System.out.println(count);
- }
- }
原文地址http://blog.csdn.net/u013087513/article/details/72851370
自己搭建的別博客 目前專講 springboot基礎 和 項目
過段時間,會抽時間專一把java環境 開發工具安裝部署等講解 有問題了可以一起探討