20160522--20160526----mybatis入门基础
一、基礎(chǔ)知識(shí):
?1.對(duì)原生態(tài)jdbc程序(單獨(dú)使用jdbc開(kāi)發(fā))問(wèn)題總結(jié)
?2.mybatis框架原理 (掌握)
?3.mybatis入門(mén)程序
?4.用戶的增、刪、改、查
?5.SqlMapConfig.xml
?6.輸入映射
?7.輸出映射
?8.動(dòng)態(tài)sql
?
1.對(duì)原生態(tài)jdbc程序中問(wèn)題總結(jié)
1.1?環(huán)境
java環(huán)境:jdk1.8.0_20
eclipse:luna
mysql:5.1
1.2 ? 創(chuàng)建mysql數(shù)據(jù)
sql腳本:
/* 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 '商品定價(jià)',`detail` text COMMENT '商品描述',`pic` varchar(64) DEFAULT NULL COMMENT '商品圖片',`createtime` datetime NOT NULL COMMENT '生產(chǎn)日期',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 '商品購(gòu)買(mǎi)數(shù)量',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 '訂單號(hào)',`createtime` datetime NOT NULL COMMENT '創(chuàng)建訂單時(shí)間',`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腳本1.3?jdbc程序
使用jdbc查詢mysql數(shù)據(jù)庫(kù)中用戶表的記錄。
創(chuàng)建java工程,加入jar包:
數(shù)據(jù)庫(kù)驅(qū)動(dòng)包(mysql5.1)
?
上邊的是mysql驅(qū)動(dòng)。
下邊的是oracle的驅(qū)動(dòng)。
?程序代碼:
package com.dzq.mybatis.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;/*** 通過(guò)Jdbc程序,總結(jié)單獨(dú)的jdbc程序,總結(jié)其中* * @author 小強(qiáng)**/ public class JdbcTest {public static void main(String[] args) {// 數(shù)據(jù)庫(kù)連接Connection connection = null;// 預(yù)編譯的Statement,可以提高數(shù)據(jù)庫(kù)的性能PreparedStatement preparedStatement = null;// 結(jié)果集對(duì)象ResultSet resultSet = null;try {// 加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)Class.forName("com.mysql.jdbc.Driver");// 通過(guò)驅(qū)動(dòng)管理類獲取數(shù)據(jù)庫(kù)鏈接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root", "mysql");// 定義sql語(yǔ)句 ?表示占位符String sql = "select * from user where username = ?";// 獲取預(yù)處理statementpreparedStatement = connection.prepareStatement(sql);// 設(shè)置參數(shù),第一個(gè)參數(shù)為sql語(yǔ)句中參數(shù)的序號(hào)(從1開(kāi)始),第二個(gè)參數(shù)為設(shè)置的參數(shù)值preparedStatement.setString(1, "王五");// 向數(shù)據(jù)庫(kù)發(fā)出sql執(zhí)行查詢,查詢出結(jié)果集resultSet = preparedStatement.executeQuery();// 遍歷查詢結(jié)果集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();}}}}} JdbcTest1.4 ?問(wèn)題總結(jié)
1、數(shù)據(jù)庫(kù)連接,使用時(shí)就創(chuàng)建,不使用立即釋放,對(duì)數(shù)據(jù)庫(kù)進(jìn)行頻繁連接開(kāi)啟和關(guān)閉,造成數(shù)據(jù)庫(kù)資源浪費(fèi),影響 數(shù)據(jù)庫(kù)性能。
設(shè)想:使用數(shù)據(jù)庫(kù)連接池管理數(shù)據(jù)庫(kù)連接。
2、將sql語(yǔ)句硬編碼到j(luò)ava代碼中,如果sql 語(yǔ)句修改,需要重新編譯java代碼,不利于系統(tǒng)維護(hù)。
設(shè)想:將sql語(yǔ)句配置在xml配置文件中,即使sql變化,不需要對(duì)java代碼進(jìn)行重新編譯。
3、向preparedStatement中設(shè)置參數(shù),對(duì)占位符號(hào)位置和設(shè)置參數(shù)值,硬編碼在java代碼中,不利于系統(tǒng)維護(hù)。
設(shè)想:將sql語(yǔ)句及占位符號(hào)和參數(shù)全部配置在xml中。
4、從resultSet中遍歷結(jié)果集數(shù)據(jù)時(shí),存在硬編碼,將獲取表的字段進(jìn)行硬編碼,,不利于系統(tǒng)維護(hù)。
設(shè)想:將查詢的結(jié)果集,自動(dòng)映射成java對(duì)象。
2.mybatis框架
2.1???? mybatis是什么?
mybatis是一個(gè)持久層的框架,是apache下的頂級(jí)項(xiàng)目。
mybatis托管到goolecode下,再后來(lái)托管到github下(https://github.com/mybatis/mybatis-3/releases)。
mybatis讓程序?qū)⒅饕Ψ旁趕ql上,通過(guò)mybatis提供的映射方式,自由靈活生成(半自動(dòng)化,大部分需要程序員編寫(xiě)sql)滿足需要sql語(yǔ)句。
mybatis可以將向 preparedStatement中的輸入?yún)?shù)自動(dòng)進(jìn)行輸入映射,將查詢結(jié)果集靈活映射成java對(duì)象。(輸出映射)
2.2 ? ?mybatis框架
3入門(mén)程序
3.1?需求
根據(jù)用戶id(主鍵)查詢用戶信息
根據(jù)用戶名稱模糊查詢用戶信息
添加用戶
刪除 用戶
更新用戶
?
3.2?環(huán)境
java環(huán)境:jdk1.8.0_20
eclipse:luna
mysql:5.1
jar包:mybatis-3.2.7.jar
lib下:依賴包
mybatis-3.2.7.jar:核心 包
mybatis-3.2.7.pdf,操作指南
加入mysql的驅(qū)動(dòng)包
3.3?log4j.properties
?
# Global logging configuration #\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u65e5\u5fd7\u7ea7\u522b\u8981\u8bbe\u7f6e\u6210DEBUG\uff0c\u751f\u4ea7\u73af\u5883\u8bbe\u7f6e\u6210info\u6216error 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%n3.4工程結(jié)構(gòu)
?
3.5?SqlMapConfig.xml
配置mybatis的運(yùn)行環(huán)境,數(shù)據(jù)源、事務(wù)等。
?
<?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事務(wù)管理,事務(wù)控制由mybatis--><transactionManager type="JDBC" /><!-- 數(shù)據(jù)庫(kù)連接池,由mybatis管理--><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></configuration> SqlMapConfig.xml?
3.6根據(jù)用戶id(主鍵)查詢用戶信息
?
3.6.1?創(chuàng)建po類
?
package com.dzq.mybatis.domain;import java.util.Date;public class User {// 屬性名和數(shù)據(jù)庫(kù)表的字段對(duì)應(yīng)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;}} User.java?
3.6.2 ? ?映射文件
映射文件命名:
User.xml(原始ibatis命名),mapper代理開(kāi)發(fā)映射文件名稱叫XXXMapper.xml,比如:UserMapper.xml、ItemsMapper.xml
在映射文件中配置sql語(yǔ)句。
<?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"> <!--命名空間,對(duì)sql進(jìn)行分類管理,實(shí)現(xiàn)sql隔離 注意:使用mapper代理的方法開(kāi)發(fā),namespace就有特殊重要的作用 --> <mapper namespace="test"><!-- 在映射文件中配置很多sql語(yǔ)句 --><!-- 通過(guò)id查詢用戶表的記錄 --><!--通過(guò)select執(zhí)行數(shù)據(jù)庫(kù)的查詢 id:標(biāo)識(shí)映射文件中的sql,稱為statemen的id 將sql語(yǔ)句封裝到mappedstatement對(duì)象中#{}:表示占位符parameterType:指定輸入?yún)?shù)類型,這里指定int型{id}:其中的id表示接收輸入?yún)?shù),如果輸入?yún)?shù)是簡(jiǎn)單類型,#{}中參數(shù)名可以任意,可以是value或者其他名稱resultType:指定sql輸出結(jié)果所映射的java對(duì)象類型,select指定resultType將單條記錄所映射成的java對(duì)象--><select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">select * from user where id=#{id}</select> </mapper> User.xml?
3.6.3 ? ? 在SqlMapConfig.xml加載映射文件
在sqlMapConfig.xml中加載User.xml:
<!-- 加載 映射文件 --><mappers><mapper resource="sqlmap/User.xml"/></mappers>3.6.4 ? ? 程序編寫(xiě)
package com.dzq.mybatis.first;import java.io.IOException; import java.io.InputStream;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 com.dzq.mybatis.domain.User;public class MybatisFirst {// 根據(jù)id查詢用戶的信息,得到一條記錄結(jié)果public void findUserById(int id) throws IOException {//mybatis配置文件String resource="SqlMapConfig.xml";//得到配置文件流InputStream inputStream=Resources.getResourceAsStream(resource);//創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);//通過(guò)工廠得到sqlsessionSqlSession sqlSession=sqlSessionFactory.openSession();//通過(guò)sqlsession操作數(shù)據(jù)庫(kù)//第一個(gè)參數(shù):statement,映射文件中statement的id; 等于namespace+"."statement的id//第二個(gè)參數(shù): parameter 指定和映射文件中parameter所匹配的parameterType的類型的 參數(shù)//sqlSession.selectOne結(jié)果是與映射文件中所匹配的resultType類型對(duì)象User user=sqlSession.selectOne("test.findUserById", 1);System.out.println(user);//釋放資源 sqlSession.close();} } MybatisFirst.java?
3.7 ?根據(jù)用戶名稱模糊查詢用戶信息
3.7.1???? 映射文件
使用User.xml,添加根據(jù)用戶名稱模糊查詢用戶信息的sql語(yǔ)句。
<!-- 根據(jù)用戶名稱模糊查詢用戶信息 --><!-- resultType:單條記錄所映射的java對(duì)象類型${}:拼接sql串,將接收到的參數(shù)不加任何修飾拼接到sql語(yǔ)句中使用${}拼接sql,會(huì)引起sql注入${value}表示輸入?yún)?shù)的內(nèi)容,如果傳入的類型是簡(jiǎn)單類型${}只能使用value--><select id="findUserByUserName" parameterType="java.lang.String" resultType="com.dzq.mybatis.domain.User">select * from user where username like '%${value}%'</select>3.7.2 ? 程序代碼
//根據(jù)用戶名稱模糊查詢用戶信息public void findUserByUserName() throws IOException{//mybatis配置文件String resource="SqlMapConfig.xml";//得到配置文件流InputStream inputStream=Resources.getResourceAsStream(resource);//創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);//通過(guò)工廠得到sqlsessionSqlSession sqlSession=sqlSessionFactory.openSession();//通過(guò)sqlsession操作數(shù)據(jù)庫(kù)//第一個(gè)參數(shù):statement,映射文件中statement的id; 等于namespace+"."statement的id//第二個(gè)參數(shù): parameter 指定和映射文件中parameter所匹配的parameterType的類型的 參數(shù)//sqlSession.selectList結(jié)果是與映射文件中所匹配的resultType類型對(duì)象List<User> list=sqlSession.selectList("test.findUserByUserName", "小明");System.out.println(list);//釋放資源 sqlSession.close();}3.8添加用戶
3.8.1映射文件
在 User.xml中配置添加用戶的Statement
<!-- 添加用戶 --><!-- parameterType:輸入?yún)?shù)類型是pojo(包括用戶信息)#{}:指定pojo的屬性名,接收到pojo的屬性值,mybatis通過(guò)ognl獲取屬性值--><insert id="addUser" parameterType="com.dzq.mybatis.domain.User">insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})</insert>?
3.8.2程序代碼
//添加用戶信息 @Testpublic void addUser() throws IOException {// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 通過(guò)工廠得到sqlsessionSqlSession sqlSession = sqlSessionFactory.openSession();//插入用戶對(duì)象User user=new User();user.setUsername("賤賤");user.setSex("男");user.setAddress("山東臨沂");user.setBirthday(new Date());sqlSession.insert("test.addUser", user);//提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}3.8.3 ? ?自增主鍵返回
mysql自增主鍵,執(zhí)行insert提交之前自動(dòng)生成一個(gè)自增主鍵。
通過(guò)mysql函數(shù)獲取到剛插入記錄的自增主鍵:
LAST_INSERT_ID()
是insert之后調(diào)用此函數(shù)。
修改insertUser定義:
<insert id="addUser" parameterType="com.dzq.mybatis.domain.User"><!-- insert 插入數(shù)據(jù)返回到User對(duì)象中 select last_insert_id:得到剛插入進(jìn)去數(shù)據(jù)的主鍵值,只適用于自增主鍵keyProperty:將要查詢到的主鍵值設(shè)置到parameterType對(duì)象的那個(gè)屬性order:相對(duì)于insert語(yǔ)句的執(zhí)行順序--><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">select last_insert_id()</selectKey>insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})</insert>3.8.14 ? ?非自增主鍵返回(使用uuid())
使用mysql的uuid()函數(shù)生成主鍵,需要修改表中id字段類型為string,長(zhǎng)度設(shè)置成35位。
執(zhí)行思路:
先通過(guò)uuid()查詢到主鍵,將主鍵輸入 到sql語(yǔ)句中。
執(zhí)行uuid()語(yǔ)句順序相對(duì)于insert語(yǔ)句之前執(zhí)行。
?
通過(guò)oracle的序列生成主鍵:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="id"> SELECT 自定義序列.NEXTVAL FROM DUAL </selectKey> insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address}) </insert>注意這里使用的order是“BEFORE”
3.9刪除用戶
3.9.1映射文件
<!-- 刪除用戶根據(jù)id刪除用戶,需要輸入id值--><delete id="deleteUser" parameterType="int" >delete from user where id=#{id}</delete>3.9.2程序代碼
//刪除用戶信息 @Testpublic void deleteUser() throws IOException {// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 通過(guò)工廠得到sqlsessionSqlSession sqlSession = sqlSessionFactory.openSession();//傳入id,根據(jù)id刪除用戶sqlSession.delete("test.deleteUser", 33);//提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}?
3.10更新用戶
3.10.1映射文件
<!-- 更新用戶 分析:需要傳入用戶的id用戶的更新信息parameterType,指定user對(duì)象,包括id和更新信息,注意,id必須存在#{id}接收user里的屬性值--><update id="updateUser" parameterType="com.dzq.mybatis.domain.User">update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}</update>3.10.2程序代碼
// 更新用戶信息 @Testpublic void updateUser() throws IOException {// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 通過(guò)工廠得到sqlsessionSqlSession sqlSession = sqlSessionFactory.openSession();User user = new User();user.setId(32);user.setUsername("賤賤賤");user.setSex("女");user.setAddress("山東萊蕪");user.setBirthday(new Date());// 傳入user對(duì)象,根據(jù)id更新用戶sqlSession.update("test.updateUser", user);// 提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}?
3.11小結(jié)
?3.11.1 ? ? ?#{}和${}
#{}表示一個(gè)占位符號(hào),#{}接收輸入?yún)?shù),類型可以是簡(jiǎn)單類型,pojo、hashmap。
如果接收簡(jiǎn)單類型,#{}中可以寫(xiě)成value或其它名稱。
#{}接收pojo對(duì)象值,通過(guò)OGNL讀取對(duì)象中的屬性值,通過(guò)屬性.屬性.屬性...的方式獲取對(duì)象屬性值。
${}表示一個(gè)拼接符號(hào),會(huì)引用sql注入,所以不建議使用${}。
${}接收輸入?yún)?shù),類型可以是簡(jiǎn)單類型,pojo、hashmap。
如果接收簡(jiǎn)單類型,${}中只能寫(xiě)成value。
${}接收pojo對(duì)象值,通過(guò)OGNL讀取對(duì)象中的屬性值,通過(guò)屬性.屬性.屬性...的方式獲取對(duì)象屬性值。
3.11.2 ? ? parameterType和resultType
parameterType:指定輸入?yún)?shù)類型,mybatis通過(guò)ognl從輸入對(duì)象中獲取參數(shù)值拼接在sql中。
resultType:指定輸出結(jié)果類型,mybatis將sql查詢結(jié)果的一行記錄數(shù)據(jù)映射為resultType指定類型的對(duì)象。
3.11.3 ? ? selectOne和selectList
selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
??? at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList可以查詢一條或多條記錄。
3.12 ? mybatis和hibernate本質(zhì)區(qū)別和應(yīng)用場(chǎng)景
hibernate:是一個(gè)標(biāo)準(zhǔn)ORM框架(對(duì)象關(guān)系映射)。入門(mén)門(mén)檻較高的,不需要程序?qū)憇ql,sql語(yǔ)句自動(dòng)生成了。
對(duì)sql語(yǔ)句進(jìn)行優(yōu)化、修改比較困難的。
應(yīng)用場(chǎng)景:
???????? 適用與需求變化不多的中小型項(xiàng)目,比如:后臺(tái)管理系統(tǒng),erp、orm、oa。。
mybatis:專注是sql本身,需要程序員自己編寫(xiě)sql語(yǔ)句,sql修改、優(yōu)化比較方便。mybatis是一個(gè)不完全 的ORM框架,雖然程序員自己寫(xiě)sql,mybatis 也可以實(shí)現(xiàn)映射(輸入映射、輸出映射)。
應(yīng)用場(chǎng)景:
???????? 適用與需求變化較多的項(xiàng)目,比如:互聯(lián)網(wǎng)項(xiàng)目。
企業(yè)進(jìn)行技術(shù)選型,以低成本 高回報(bào)作為技術(shù)選型的原則,根據(jù)項(xiàng)目組的技術(shù)力量進(jìn)行選擇。
4 ? ? mybatis開(kāi)發(fā)dao的方法
4.1???? SqlSession使用范圍
4.1.1???? SqlSessionFactoryBuilder
?通過(guò)SqlSessionFactoryBuilder創(chuàng)建會(huì)話工廠SqlSessionFactory
將SqlSessionFactoryBuilder當(dāng)成一個(gè)工具類使用即可,不需要使用單例管理SqlSessionFactoryBuilder。
在需要?jiǎng)?chuàng)建SqlSessionFactory時(shí)候,只需要new一次SqlSessionFactoryBuilder即可。
4.1.2 ??SqlSessionFactory
通過(guò)SqlSessionFactory創(chuàng)建SqlSession,使用單例模式管理sqlSessionFactory(工廠一旦創(chuàng)建,使用一個(gè)實(shí)例)。
將來(lái)mybatis和spring整合后,使用單例模式管理sqlSessionFactory。
?
4.1.3 ? ?SqlSession
SqlSession是一個(gè)面向用戶(程序員)的接口。
SqlSession中提供了很多操作數(shù)據(jù)庫(kù)的方法:如:selectOne(返回單個(gè)對(duì)象)、selectList(返回單個(gè)或多個(gè)對(duì)象)、。
SqlSession是線程不安全的,在SqlSesion實(shí)現(xiàn)類中除了有接口中的方法(操作數(shù)據(jù)庫(kù)的方法)還有數(shù)據(jù)域?qū)傩浴?/p>
SqlSession最佳應(yīng)用場(chǎng)合在方法體內(nèi),定義成局部變量使用。
4.2 ? ?原始dao開(kāi)發(fā)方法(程序員需要寫(xiě)dao接口和dao實(shí)現(xiàn)類)
4.2.1???? 思路
程序員需要寫(xiě)dao接口和dao實(shí)現(xiàn)類。
需要向dao實(shí)現(xiàn)類中注入SqlSessionFactory,在方法體內(nèi)通過(guò)SqlSessionFactory創(chuàng)建SqlSession
4.2.2 ? ? dao接口
package com.dzq.mybatis.dao;import com.dzq.mybatis.domain.User;public interface UserDao {// 根據(jù)id查詢用戶信息public User findUserById(int id) throws Exception;// 添加用戶public void addUser(User user) throws Exception;// 刪除用戶public void deleteUser(int id) throws Exception;// 修改用戶信息public void updateUser(User user) throws Exception; }?
4.2.2 ? ? dao接口實(shí)現(xiàn)類
package com.dzq.mybatis.dao.impl;import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory;import com.dzq.mybatis.dao.UserDao; import com.dzq.mybatis.domain.User;public class UserDaoImpl implements UserDao {// 需要向dao實(shí)現(xiàn)類中注入SqlSessionFactory// 這里通過(guò)構(gòu)造方法注入private SqlSessionFactory sqlSessionFactory;public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic User findUserById(int id) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();User user = sqlSession.selectOne("test.findUserById", id);// 釋放資源 sqlSession.close();return user;}@Overridepublic void addUser(User user) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 執(zhí)行插入sqlSession.insert("test.addUser", user);// 提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}@Overridepublic void deleteUser(int id) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.delete("test.deleteUser", id);// 提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}@Overridepublic void updateUser(User user) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.update("test.updateUser", user);// 提交事務(wù) sqlSession.commit();// 釋放資源 sqlSession.close();}}4.2.4 ?測(cè)試代碼:
package com.dzq.mybatis.test;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 com.dzq.mybatis.dao.UserDao; import com.dzq.mybatis.dao.impl.UserDaoImpl; import com.dzq.mybatis.domain.User;public class UserDaoImplTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUp() throws Exception {// 創(chuàng)建sqlSessionFactory// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception {// 創(chuàng)建UserDao對(duì)象UserDao userdao = new UserDaoImpl(sqlSessionFactory);// 調(diào)用userDao方法User user=userdao.findUserById(1);System.out.println(user.getUsername());}}?
4.2.5 ? ? 總結(jié)原始 dao開(kāi)發(fā)問(wèn)題
1、dao接口實(shí)現(xiàn)類方法中存在大量模板方法,設(shè)想能否將這些代碼提取出來(lái),大大減輕程序員的工作量。
?
2、調(diào)用sqlsession方法時(shí)將statement的id硬編碼了
?
3、調(diào)用sqlsession方法時(shí)傳入的變量,由于sqlsession方法使用泛型,即使變量類型傳入錯(cuò)誤,在編譯階段也不報(bào)錯(cuò),不利于程序員開(kāi)發(fā)。
?
4.3 ? ?mapper代理方法(程序員只需要mapper接口(相當(dāng) 于dao接口))
?
4.3.1???? 思路(mapper代理開(kāi)發(fā)規(guī)范)
程序員還需要編寫(xiě)mapper.xml映射文件
程序員編寫(xiě)mapper接口需要遵循一些開(kāi)發(fā)規(guī)范,mybatis可以自動(dòng)生成mapper接口實(shí)現(xiàn)類代理對(duì)象。
?
開(kāi)發(fā)規(guī)范:
1、在mapper.xml中namespace等于mapper接口地址
<!--命名空間,對(duì)sql進(jìn)行分類管理,實(shí)現(xiàn)sql隔離 注意:使用mapper代理的方法開(kāi)發(fā),namespace就有特殊重要的作用 namespace等于mapper接口地址 --> <mapper namespace="com.dzq.mybatis.mapper.UserMapper">?
2、mapper.java接口中的方法名和mapper.xml中statement的id一致
3、mapper.java接口中的方法輸入?yún)?shù)類型和mapper.xml中statement的parameterType指定的類型一致。
4、mapper.java接口中的方法返回值類型和mapper.xml中statement的resultType指定的類型一致。
<select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">select * from user where id=#{id}</select> // 根據(jù)id查詢用戶信息public User findUserById(int id) throws Exception;總結(jié):
以上開(kāi)發(fā)規(guī)范主要是對(duì)下邊的代碼進(jìn)行統(tǒng)一生成:
User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
。。。。
4.3.2 ? ??mapper.java
package com.dzq.mybatis.mapper;import java.util.List;import com.dzq.mybatis.domain.User;public interface UserMapper {public User findUserById(int id) throws Exception; }4.3.3?mapper.xml
<select id="findUserById" parameterType="int" resultType="com.dzq.mybatis.domain.User">select * from user where id=#{id}</select>4.3.4 ? ? 在SqlMapConfig.xml中加載mapper.xml
<!-- 加載 映射文件 --><mappers><mapper resource="sqlmap/User.xml"/><mapper resource="mapper/UserMapper.xml"/></mappers>4.3.5 ? ?測(cè)試
package com.dzq.mybatis.test;import java.io.InputStream;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 com.dzq.mybatis.domain.User; import com.dzq.mybatis.mapper.UserMapper;public class UserMapperTest {private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUp() throws Exception {// 創(chuàng)建sqlSessionFactory// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 創(chuàng)建會(huì)話工廠,傳入mybatis的配置文件的信息sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception {SqlSession sqlSession=sqlSessionFactory.openSession();//創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper=sqlSession.getMapper(UserMapper.class);//調(diào)用userMapper方法User user=userMapper.findUserById(1);System.out.println(user.getUsername());}}4.3.6 ? ?整個(gè)接口
package com.dzq.mybatis.mapper;import java.util.List;import com.dzq.mybatis.domain.User;public interface UserMapper {// 根據(jù)id查詢用戶信息public User findUserById(int id) throws Exception;// 添加用戶public void addUser(User user) throws Exception;// 刪除用戶public void deleteUser(int id) throws Exception;// 根據(jù)用戶名稱查詢用戶列表public List<User> findUserByUserName(String username) throws Exception; }4.3.7 ? ? 一些問(wèn)題總結(jié)
4.3.7.1????????????? 代理對(duì)象內(nèi)部調(diào)用selectOne或selectList
如果mapper方法返回單個(gè)pojo對(duì)象(非集合對(duì)象),代理對(duì)象內(nèi)部通過(guò)selectOne查詢數(shù)據(jù)庫(kù)。
如果mapper方法返回集合對(duì)象,代理對(duì)象內(nèi)部通過(guò)selectList查詢數(shù)據(jù)庫(kù)。
4.3.7.2????????????? mapper接口方法參數(shù)只能有一個(gè)是否影響系統(tǒng) 開(kāi)發(fā)
mapper接口方法參數(shù)只能有一個(gè),系統(tǒng)是否不利于擴(kuò)展維護(hù)。
系統(tǒng) 框架中,dao層的代碼是被業(yè)務(wù)層公用的。
即使mapper接口只有一個(gè)參數(shù),可以使用包裝類型的pojo滿足不同的業(yè)務(wù)方法的需求。
?
注意:持久層方法的參數(shù)可以包裝類型、map。。。,service方法中建議不要使用包裝類型(不利于業(yè)務(wù)層的可擴(kuò)展)。
?
5 ? ??SqlMapConfig.xml
mybatis的全局配置文件SqlMapConfig.xml,配置內(nèi)容如下:
?
properties(屬性)
settings(全局配置參數(shù))
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對(duì)象工廠)
plugins(插件)
environments(環(huán)境集合屬性對(duì)象)
environment(環(huán)境子屬性對(duì)象)
transactionManager(事務(wù)管理)
dataSource(數(shù)據(jù)源)
mappers(映射器)
?
5.1???? properties屬性
需求:
將數(shù)據(jù)庫(kù)連接參數(shù)單獨(dú)配置在db.properties中,只需要在SqlMapConfig.xml中加載db.properties的屬性值。
在SqlMapConfig.xml中就不需要對(duì)數(shù)據(jù)庫(kù)連接參數(shù)硬編碼。
?
將數(shù)據(jù)庫(kù)連接參數(shù)只配置在db.properties中,原因:方便對(duì)參數(shù)進(jìn)行統(tǒng)一管理,其它xml可以引用該db.properties。
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password= <!-- 加載屬性文件 --><properties resource="db.properties"><!--properties中還可以配置一些屬性名和屬性值 --><!-- <property name="jdbc.driver" value=""/> --></properties>properties特性:
?
注意: MyBatis 將按照下面的順序來(lái)加載屬性:
? ? ? 在 properties 元素體內(nèi)定義的屬性首先被讀取。
? ? ? 然后會(huì)讀取properties 元素中resource或 url 加載的屬性,它會(huì)覆蓋已讀取的同名屬性。
? ? ? 最后讀取parameterType傳遞的屬性,它會(huì)覆蓋已讀取的同名屬性。
?
建議:
不要在properties元素體內(nèi)添加任何屬性值,只將屬性值定義在properties文件中。
在properties文件中定義屬性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX
5.2 ? settings全局參數(shù)配置
?
mybatis框架在運(yùn)行時(shí)可以調(diào)整一些運(yùn)行參數(shù)。
比如:開(kāi)啟二級(jí)緩存、開(kāi)啟延遲加載。。
?
全局參數(shù)將會(huì)影響mybatis的運(yùn)行行為。
?
5.3 ? ? typeAliases(別名)重點(diǎn)
?
5.3.1???? 需求
在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入?yún)?shù)的類型、需要resultType指定輸出結(jié)果的映射類型。
?
如果在指定類型時(shí)輸入類型全路徑,不方便進(jìn)行開(kāi)發(fā),可以針對(duì)parameterType或resultType指定的類型定義一些別名,在mapper.xml中通過(guò)別名定義,方便開(kāi)發(fā)。
5.3.2 ? mybatis默認(rèn)支持別名
5.3.3 ? ? 自定義別名
?
5.3.3.1????????????? 單個(gè)別名定義
<!-- 別名定義 --><typeAliases><!-- 針對(duì)單個(gè)別名的定義type:類型路徑alias:別名--><typeAlias type="com.dzq.mybatis.domain.User" alias="user"/></typeAliases>?
引用別名:
<select id="findUserById" parameterType="int" resultType="user">select * from user where id=#{id}</select>5.3.3.2??批量定義別名(常用)
<!-- 批量別名定義指定包名,mybatis自動(dòng)掃描domain類,自動(dòng)定義別名,別名就是類名--><package name="com.dzq.mybatis.domain"/>5.4 ? ?typeHandlers(類型處理器)
mybatis中通過(guò)typeHandlers完成jdbc類型和java類型的轉(zhuǎn)換。
?
通常情況下,mybatis提供的類型處理器滿足日常需要,不需要自定義.
?
mybatis支持類型處理器:
5.5 ?mappers(映射配置)
5.5.1???? 通過(guò)resource加載單個(gè)映射文件
<!-- 加載 映射文件 --><mappers><mapper resource="sqlmap/User.xml" /><mapper resource="mapper/UserMapper.xml" /></mappers>5.5.2 ? 通過(guò)mapper接口加載單個(gè)mapper
<!--通過(guò)mapper接口加載單個(gè)mapper 遵循一些規(guī)范:需要將mapper接口的類名和mapper.xml映射文件名稱保持一致,且在一個(gè)目錄上邊規(guī)范的前提是:你使用的是mapper代理的方法--><mapper class="com.dzq.mybatis.mapper.UserMapper"/>需要將mapper接口的類名和mapper.xml映射文件名稱保持一致,且在一個(gè)目錄
5.5.3 ?批量加載mapper(推薦使用)
<!--批量加載mapper(推薦使用) 指定mapper接口的包名,mybatis自動(dòng)掃描包下所有mapper接口進(jìn)行加載遵循一些規(guī)范:需要將mapper接口的類名和mapper.xml映射文件名稱保持一致,且在一個(gè)目錄上邊規(guī)范的前提是:你使用的是mapper代理的方法--><package name="com.dzq.mybatis.mapper"/>6 ? ?輸入映射
通過(guò)parameterType指定輸入?yún)?shù)的類型,類型可以是簡(jiǎn)單類型、hashmap、pojo的包裝類型。
6.1???? 傳遞pojo的包裝對(duì)象
6.1.1???? 需求
完成用戶信息的綜合查詢,需要傳入查詢條件很復(fù)雜(可能包括用戶信息、其它信息,比如商品、訂單的)
6.1.2???? 定義包裝類型pojo
針對(duì)上邊需求,建議使用自定義的包裝類型的pojo。
在包裝類型的pojo中將復(fù)雜的查詢條件包裝進(jìn)去。
package com.dzq.mybatis.domain;public class UserQueryVo { //這里包裝所需要的查詢條件//用戶查詢條件private UserCustom userCustom;//還可以包裝其他的查詢條件 商品、訂單public UserCustom getUserCustom() {return userCustom;}public void setUserCustom(UserCustom userCustom) {this.userCustom = userCustom;}}6.1.3 ? ?mapper.xml
在UserMapper.xml中定義用戶信息綜合查詢(查詢條件復(fù)雜,通過(guò)高級(jí)查詢進(jìn)行復(fù)雜關(guān)聯(lián)查詢)。
<!-- 用戶信息的綜合查詢#{userCustom.sex}:取出包裝類型的性別信息${userCustom.username}:取出包裝類中的用戶名--><select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">select * from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'</select>6.1.4 ? ??mapper.java
//用戶信息綜合查詢public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;?
6.1.5 ? ?測(cè)試代碼
@Testpublic void testFindUserList() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//創(chuàng)建包裝對(duì)象,設(shè)置查詢條件UserQueryVo userQueryVo=new UserQueryVo();UserCustom userCustom=new UserCustom();userCustom.setSex("1");userCustom.setUsername("小明");userQueryVo.setUserCustom(userCustom);// 調(diào)用userMapper方法 List<UserCustom> list = userMapper.findUserList(userQueryVo);//sqlSession.close(); System.out.println(list);}?
7 ? ? 輸出映射
?
7.1???? resultType
使用resultType進(jìn)行輸出映射,只有查詢出來(lái)的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來(lái)的列名和pojo中的屬性名全部不一致,沒(méi)有創(chuàng)建pojo對(duì)象。
只要查詢出來(lái)的列名和pojo中的屬性有一個(gè)一致,就會(huì)創(chuàng)建pojo對(duì)象,不一致的屬性的值為null。
?
7.1.1???? 輸出簡(jiǎn)單類型
7.1.1.1????????????? 需求
用戶信息的綜合查詢列表總數(shù),通過(guò)查詢總數(shù)和上邊用戶綜合查詢列表才可以實(shí)現(xiàn)分頁(yè)。
?
7.1.1.2????????????? mapper.xml
<!-- 用戶信息綜合查詢總數(shù)parameterType:輸入類型和findUserList一致resultType:輸出結(jié)果類型為整型--><select id="findUserCount" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">select count(*) from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'</select>?
7.1.1.3 ? ? ? ? ? ? ?mapper.java
//用戶信息綜合查詢總數(shù)public int findUserCount(UserQueryVo userQueryVo) throws Exception;?
7.1.1.4 ? ? ? ? ? ? 測(cè)試代碼
@Testpublic void testFindUserCount() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//創(chuàng)建包裝對(duì)象,設(shè)置查詢條件UserQueryVo userQueryVo=new UserQueryVo();UserCustom userCustom=new UserCustom();userCustom.setSex("1");userCustom.setUsername("小明");userQueryVo.setUserCustom(userCustom);// 調(diào)用userMapper方法int count = userMapper.findUserCount(userQueryVo);System.out.println(count);}7.1.1.5 ? ? ? ? ? ? 小結(jié)
查詢出來(lái)的結(jié)果集只有一行且一列,可以使用簡(jiǎn)單類型進(jìn)行輸出映射。
7.1.2 ? 輸出pojo對(duì)象和pojo列表
?
不管是輸出的pojo單個(gè)對(duì)象還是一個(gè)列表(list中包括pojo),在mapper.xml中resultType指定的類型是一樣的。
在mapper.java指定的方法返回值類型不一樣:
???????? 1、輸出單個(gè)pojo對(duì)象,方法返回值是單個(gè)對(duì)象類型
? ? ? ? ??
// 根據(jù)id查詢用戶信息public User findUserById(int id) throws Exception;?
? ? ? ? ?2、輸出pojo對(duì)象list,方法返回值是List<Pojo>
? ? ? ? ?
// 根據(jù)用戶名稱查詢用戶列表public List<User> findUserByUserName(String username) throws Exception;?
生成的動(dòng)態(tài)代理對(duì)象中是根據(jù)mapper方法的返回值類型確定是調(diào)用selectOne(返回單個(gè)對(duì)象調(diào)用)還是selectList (返回集合對(duì)象調(diào)用 ).
7.2 ? ? resultMap
mybatis中使用resultMap完成高級(jí)輸出結(jié)果映射。(一對(duì)一、一對(duì)多、多對(duì)多)(小入門(mén))
7.2.1???? resultMap使用方法
如果查詢出來(lái)的列名和pojo的屬性名不一致,通過(guò)定義一個(gè)resultMap對(duì)列名和pojo屬性名之間作一個(gè)映射關(guān)系。
1、定義resultMap
2、使用resultMap作為statement的輸出映射類型
7.2.2???? 將下邊的sql使用User完成映射
SELECT id id_,username username_ FROM USER WHERE id=#{value}
User類中屬性名和上邊查詢列名不一致。
7.2.2.1????????????? 定義reusltMap
<!-- 定義resultMap將 select id id_,username username_ from user where id=#{id}查詢和User做一個(gè)映射type:resultMap最終映射的java對(duì)象類型,可以使用別名id:對(duì)resultMap的唯一標(biāo)識(shí)--><resultMap type="user" id="userResultMap"><!-- id表示查詢結(jié)果集中唯一的標(biāo)識(shí) column:查詢出來(lái)的列名property:type中指定的pojo中的屬性名最終resultMap對(duì)column和property做一個(gè)映射關(guān)系(對(duì)應(yīng)關(guān)系)--><id column="id_" property="id"/><!-- 對(duì)普通列的定義column:查詢出來(lái)的列名property:type中指定的pojo中的屬性名最終resultMap對(duì)column和property做一個(gè)映射關(guān)系(對(duì)應(yīng)關(guān)系)--><result column="username_" property="username"/></resultMap>?
7.2.2.2 ? ? ??使用resultMap作為statement的輸出映射類型
<!-- 使用resultMap來(lái)進(jìn)行輸出的映射 resultMap:指定定義的resultMap的id,如果resultMap在其他映射文件中,前邊需要加上namespace--><select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">select id id_,username username_ from user where id=#{id}</select>7.2.2.3 ? ? ? ? ? ?mapper.java
//根據(jù)id查詢用戶信息,使用resultMap輸出public User findUserByIdResultMap(int id)throws Exception;7.2.2.4 ? ? ? ? ? ?測(cè)試
@Testpublic void testFindUserByIdResultMap() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 調(diào)用userMapper方法User user = userMapper.findUserByIdResultMap(1);System.out.println(user.getUsername());}7.3 ? ?小結(jié)
使用resultType進(jìn)行輸出映射,只有查詢出來(lái)的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來(lái)的列名和pojo的屬性名不一致,通過(guò)定義一個(gè)resultMap對(duì)列名和pojo屬性名之間作一個(gè)映射關(guān)系。
8 ? ? ?動(dòng)態(tài)sql
8.1???? 什么是動(dòng)態(tài)sql
mybatis核心 對(duì)sql語(yǔ)句進(jìn)行靈活操作,通過(guò)表達(dá)式進(jìn)行判斷,對(duì)sql進(jìn)行靈活拼接、組裝。
8.2???? 需求
用戶信息綜合查詢列表和用戶信息查詢列表總數(shù)這兩個(gè)statement的定義使用動(dòng)態(tài)sql。
對(duì)查詢條件進(jìn)行判斷,如果輸入?yún)?shù)不為空才進(jìn)行查詢條件拼接。
8.3???? mapper.xml
<!-- 用戶信息的綜合查詢#{userCustom.sex}:取出包裝類型的性別信息${userCustom.username}:取出包裝類中的用戶名--><select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">select * from user <!-- where 可以自動(dòng)的去掉條件中的第一個(gè)and --><where><if test="userCustom!=null"><if test="userCustom.sex!=null and userCustom.sex!=''">and user.sex=#{userCustom.sex} </if><if test="userCustom.username!=null and userCustom.username!=''">and user.username like '%${userCustom.username}%'</if></if></where></select><!-- 用戶信息綜合查詢總數(shù)parameterType:輸入類型和findUserList一致resultType:輸出結(jié)果類型為整型--><select id="findUserCount" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">select count(*) from user <!-- where 可以自動(dòng)的去掉條件中的第一個(gè)and --><where><if test="userCustom!=null"><if test="userCustom.sex!=null and userCustom.sex!=''">and user.sex=#{userCustom.sex} </if><if test="userCustom.username!=null and userCustom.username!=''">and user.username like '%${userCustom.username}%'</if></if></where></select>8.4 ? 測(cè)試代碼
public void testFindUserList() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//創(chuàng)建包裝對(duì)象,設(shè)置查詢條件UserQueryVo userQueryVo=new UserQueryVo();UserCustom userCustom=new UserCustom();//由于使用了動(dòng)態(tài)sql,如果不設(shè)置某個(gè)值,這個(gè)條件不會(huì)拼接到sql中//userCustom.setSex("1");userCustom.setUsername("小明");userQueryVo.setUserCustom(userCustom);// 調(diào)用userMapper方法 List<UserCustom> list = userMapper.findUserList(userQueryVo);//sqlSession.close(); System.out.println(list);}8.5 ? ?sql片段
?
8.5.1???? 需求
將上邊實(shí)現(xiàn)的動(dòng)態(tài)sql判斷代碼塊抽取出來(lái),組成一個(gè)sql片段。其它的statement中就可以引用sql片段。
方便程序員進(jìn)行開(kāi)發(fā)。
?
8.5.2???? 定義sql片段
!--定義sql片段id:sql片段的唯一標(biāo)識(shí)經(jīng)驗(yàn):基于單表定義sql片段,這樣可重用性才高sql片段中不要包括where--><sql id="query_user_where"><if test="userCustom!=null"><if test="userCustom.sex!=null and userCustom.sex!=''">and user.sex=#{userCustom.sex} </if><if test="userCustom.username!=null and userCustom.username!=''">and user.username like '%${userCustom.username}%'</if></if></sql>?
8.5.3 ? ?引用sql片段
在mapper.xml中定義的statement中引用sql片段:
<!-- 用戶信息的綜合查詢#{userCustom.sex}:取出包裝類型的性別信息${userCustom.username}:取出包裝類中的用戶名--><select id="findUserList" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="com.dzq.mybatis.domain.UserCustom">select * from user <!-- where 可以自動(dòng)的去掉條件中的第一個(gè)and --><where><!-- 這就是引用sql片段的id 如果refid不在本mapper中,需要加上namespace--><include refid="query_user_where"> </include><!-- 在這里還會(huì)引用其他sql片段,商品等 --></where></select> <!-- 用戶信息綜合查詢總數(shù)parameterType:輸入類型和findUserList一致resultType:輸出結(jié)果類型為整型--><select id="findUserCount" parameterType="com.dzq.mybatis.domain.UserQueryVo" resultType="int">select count(*) from user <!-- where 可以自動(dòng)的去掉條件中的第一個(gè)and --><where><!-- 這就是引用sql片段的id 如果refid不在本mapper中,需要加上namespace--><include refid="query_user_where"> </include><!-- 在這里還會(huì)引用其他sql片段,商品等 --></where></select>?
8.6 ? ?foreach
?
向sql傳遞數(shù)組或List,mybatis使用foreach解析
?
8.6.1???? 需求
?
在用戶查詢列表和查詢總數(shù)的statement中增加多個(gè)id輸入查詢。
sql語(yǔ)句如下:
兩種方法:
SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)
8.6.2 ? ?在輸入?yún)?shù)類型中添加List<Integer> ids傳入多個(gè)id
?
//傳入多個(gè)idprivate List<Integer> ids;public List<Integer> getIds() {return ids;}public void setIds(List<Integer> ids) {this.ids = ids;}?
8.6.3 ? ? 修改mapper.xml
WHERE id=1 OR id=10 OR id=16
在查詢條件中,查詢條件定義成一個(gè)sql片段,需要修改sql片段。
<if test="ids!=null"><!-- 使用foreach遍歷我們傳入的ids collection:指定輸入對(duì)象中集合屬性item:每次遍歷生成對(duì)象名open:開(kāi)始遍歷時(shí)要拼接的串close:結(jié)束遍歷時(shí)拼接的串separator:遍歷的兩個(gè)對(duì)象中間所要拼接的串--><!-- 使用實(shí)現(xiàn)下邊的sql拼接and (id=1 or id=10 or id=16)--><foreach collection="ids" item="user_id" open="and (" close=")" separator="or"><!-- 每次遍歷所需要拼接的串-->id=#{user_id}</foreach></if>?
8.6.4 ? ? 測(cè)試代碼
@Testpublic void testFindUserList() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();// 創(chuàng)建一個(gè)usermapper的對(duì)象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//創(chuàng)建包裝對(duì)象,設(shè)置查詢條件UserQueryVo userQueryVo=new UserQueryVo();UserCustom userCustom=new UserCustom();//由于使用了動(dòng)態(tài)sql,如果不設(shè)置某個(gè)值,這個(gè)條件不會(huì)拼接到sql中userCustom.setSex("1");userCustom.setUsername("小明");//傳入多個(gè)idList <Integer> ids=new ArrayList<Integer>();ids.add(1);ids.add(10);ids.add(16);userQueryVo.setUserCustom(userCustom);//將ids傳入statement中 userQueryVo.setIds(ids);// 調(diào)用userMapper方法 List<UserCustom> list = userMapper.findUserList(userQueryVo);//sqlSession.close();System.out.println(list.get(0).getUsername());}?
8.6.5 ?另外一個(gè)sql的實(shí)現(xiàn):
?
<!--實(shí)現(xiàn) and id in(1,10,16)拼接 --><foreach collection="ids" item="user_id" open=" and id in(" close=")" separator=","><!-- 每次遍歷所需要拼接的串-->#{user_id}</foreach>?
轉(zhuǎn)載于:https://www.cnblogs.com/xiaoduc-org/p/5517727.html
總結(jié)
以上是生活随笔為你收集整理的20160522--20160526----mybatis入门基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: zabbix 邮件报警
- 下一篇: 数据、事实、实体、值对象、事务、不变性