1. 總結jdbc開發的問題
1.
頻繁創建數據庫連接對象、釋放,容易造成系統資源浪費,影響系統性能。企業項目中可以使用連接池解決這個問題,但是使用Jdbc需要自己實現連接池。mybatis已經提供了連接池。
2.
sql語句定義、參數設置、結果集處理存在硬編碼。企業項目中,sql語句變化的可能性較大,一旦發生變化,需要修改Java代碼,系統需要重新編譯,重新發布。不好維護。
3.
結果集處理存在重複代碼,處理麻煩。如果可以映射爲java對象會比較方便。
2.
mybatis介紹
mybatis是Apache軟件基金會下的一個開源項目,前身是Ibatis框架。2010年這個項目由apache
軟件基金會遷移到google code下,改名爲mybatis。2013年11月又遷移到了github(https://github.com/mybatis/mybatis-3/releases)。
mybatis是一個持久層的框架,是對JDBC操作數據庫的封裝,使開發者只需要關注業務本身,不需要花費精力去處理加載驅動、創建數據庫連接對象、創建statement語句對象、參數設置、結果集處理等一系列繁雜的過程代碼。
mybatis通過xml或註解進行配置,將java對象與sql語句中的參數自動映射生成最終執行的sql語句,並將sql語句執行結果自動映射成java對象,返回給業務層(service)應用。
3.
mybatis入門程序
3.1.
需求
實現用戶表(user)增、刪、改、查操作。
1.
根據用戶Id查詢用戶
2.
根據用戶名稱模糊查詢用戶
3.
新增用戶
4.
根據用戶Id修改用戶
5.
根據用戶Id刪除用戶
3.2.
需求實現
3.2.1.
配置pom.xml文件,加入mybatis依賴
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itheima</groupId>
<artifactId>mybatis-first</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mybatis-first</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--
mysql版本 -->
<mysql.version>5.1.30</mysql.version>
<!--
junit版本 -->
<junit.version>4.12</junit.version>
<!--
mybatis版本號 -->
<mybatis.version>3.4.5</mybatis.version>
<!-- log4j日誌包版本 -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<!--
mysql數據庫依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--
mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- log4j日誌包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--
junit依賴 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
|
3.2.2.
準備配置文件
3.2.2.1. sqlMapConfig.xml
說明:mybatis框架核心配置文件。
<?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>
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments
default="development">
<!-- id屬性:唯一標識一個運行環境 -->
<environment
id="development">
<!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務
-->
<transactionManager
type="JDBC"
/>
<!-- 數據源配置,POOLED:mybatis提供的連接池 -->
<dataSource
type="POOLED">
<property
name="driver"
value="com.mysql.jdbc.Driver"
/>
<property
name="url"
value="jdbc:mysql://127.0.0.1:3306/mybatis"
/>
<property
name="username"
value="root"
/>
<property
name="password"
value="admin"
/>
</dataSource>
</environment>
</environments>
</configuration>
|
3.2.2.2. log4j.properties
# Global logging configuration
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
|
3.2.3.
準備用戶pojo
public
class User {
private Integer
id;
//
int(11) NOT NULL AUTO_INCREMENT,
private String
username;
//
varchar(32) NOT NULL COMMENT '用戶名稱',
private Date
birthday;
// date DEFAULT NULL COMMENT '生日',
private String
sex;
// char(1) DEFAULT NULL COMMENT '性別',
private String
address;
//
varchar(256) DEFAULT NULL COMMENT '地址',
/**
*
@return the id
*/
public
Integer getId() {
return
id;
}
/**
*
@param id the id
to set
*/
public
void setId(Integer id)
{
this.id
= id;
}
/**
*
@return the
username
*/
public
String getUsername() {
return
username;
}
/**
*
@param username
the username to set
*/
public
void setUsername(String
username) {
this.username
= username;
}
/**
*
@return the birthday
*/
public
Date getBirthday() {
return
birthday;
}
/**
*
@param birthday
the birthday to set
*/
public
void setBirthday(Date birthday)
{
this.birthday
= birthday;
}
/**
*
@return the sex
*/
public
String getSex() {
return
sex;
}
/**
*
@param sex the sex
to set
*/
public
void setSex(String sex)
{
this.sex
= sex;
}
/**
*
@return the address
*/
public
String getAddress() {
return
address;
}
/**
*
@param address the
address to set
*/
public
void setAddress(String
address) {
this.address
= address;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public
String toString() {
return
"User [id=" +
id +
", username=" +
username +
", birthday="
+
birthday +
", sex=" +
sex +
", address=" +
address +
"]";
}
}
|
3.2.4.
準備sql語句
select * from `user` where id=24
|
3.2.5.
準備mapper映射文件
說明:用於配置java對象,與sql語句的對應關係。
<?xml
version="1.0"
encoding="UTF-8"
?>
<!DOCTYPE
mapper
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace屬性:名稱空間,相當於java中的package,用於放置sql語句衝突
-->
<mapper
namespace="test">
<!--說明:mybatis框架針對每一種sql語句:新增/修改/刪除/查詢,提供了對應的標籤:
insert/update/delete/select來放置 -->
<!-- 根據用戶Id查詢用戶,說明:
select標籤:用於放置查詢sql語句
id屬性:唯一標識一條sql語句
parameterType屬性:輸入參數類型
resultType屬性:返回值類型
#{id}:佔位符,相當於jdbc中的問號:?-->
<select
id="queryUserById"
parameterType="int"
resultType="cn.itheima.mybatis.po.User">
select * from `user` where id=#{id}
</select>
</mapper>
|
3.2.6.
在sqlMapcConfig.xml文件中,加載User.xml文件
<?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>
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments
default="development">
<!-- id屬性:唯一標識一個運行環境 -->
<environment
id="development">
<!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務
-->
<transactionManager
type="JDBC"
/>
<!-- 數據源配置,POOLED:mybatis提供的連接池 -->
<dataSource
type="POOLED">
<property
name="driver"
value="com.mysql.jdbc.Driver"
/>
<property
name="url"
value="jdbc:mysql://127.0.0.1:3306/mybatis"
/>
<property
name="username"
value="root"
/>
<property
name="password"
value="admin"
/>
</dataSource>
</environment>
</environments>
<!-- 加載mapper映射文件
-->
<mappers>
<!--加載User.xml文件,說明:
resource屬性:指定配置文件的位置-->
<mapper resource="sqlmap/User.xml"/>
</mappers>
</configuration>
|
3.2.7.
編寫測試代碼
public
class MybatisTest {
// 1.測試根據用戶Id查詢用戶
@Test
public
void queryUserByIdTest()
throws IOException{
// 1.加載核心配置文件:sqlMapConfig.xml
// resource屬性:指定核心配置文件位置
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.讀取配置文件內容
SqlSessionFactoryBuilder builder =
new SqlSessionFactoryBuilder();
// SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
// 3.使用SqlSessionFactory對象,創建sqlSession對象
// sqlSession對象:
// 3.1相當於jdbc中的connection對象
// 3.2 sqlSession對象是線程不安全,每一個執行操作的方法,都需要創建一個sqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession對象,調用方法執行
// selectOne方法:查詢單條記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
Object user = sqlSession.selectOne("test.queryUserById",
24);
System.out.println(user);
// 5.釋放資源
sqlSession.close();
}
}
|
3.3.
其他需求實現
3.3.1.
根據用戶名稱模糊查詢用戶
3.3.1.1. 準備sql語句
select * from `user` where username like '%小明%'
|
3.3.1.2. 配置映射文件
<!-- 根據用戶名稱模糊查詢用戶,說明 -->
<select
id="queryUserByName"
parameterType="string"
resultType="cn.itheima.mybatis.po.User">
select * from `user` where
username like #{username}
</select>
|
3.3.1.3. 編寫測試代碼
// 2.測試根據用戶名稱模糊查詢用戶
@Test
public
void
queryUserByNameTest()
throws IOException{
// 1.加載核心配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.讀取配置文件內容
SqlSessionFactoryBuilder builder =
new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
// 3.使用sqlSessionFactory對象,創建sqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4.使用sqlSession對象,調用方法執行
// selectList方法:查詢多條記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
List<Object> list = sqlSession.selectList("test.queryUserByName",
"%小明%");
for(Object o :list){
System.out.println(o);
}
// 5.釋放資源
sqlSession.close();
}
|
3.3.1.4. 使用字符串拼接符${},拼接參數
<!-- 根據用戶名稱模糊查詢用戶,說明 -->
<select
id="queryUserByName"
parameterType="string"
resultType="cn.itheima.mybatis.po.User">
<!-- select * from `user` where
username like #{username}
-->
<!-- where
username like '%小明%',說明:
使用字符串拼接符${},拼接參數 -->
select * from `user` where
username like '%${value}%'
</select>
|
3.3.1.5. 佔位符#{}與字符串拼接符${}區別
1. 佔位符#{},相當於jdbc中的問號?,當參數傳遞的是java簡單類型的時候,花括號中的內容可以是任意字符串。
2. 字符串拼接符 ${},當參數傳遞的是java簡單類型的時候,花括號中的內容只能是:value
3. 在sql語句中使用字符串拼接符${},可能引起sql注入的問題。但是mybatis中字符串拼接符可以使用,原因是是後端dao層的開發,項目中參數傳遞經過表現層(action),業務層(service)已經處理好。
3.3.2.
新增用戶
3.3.2.1. 準備sql語句
insert into `user`(id,username,birthday,sex,address) values(2,'小李飛刀','2017-11-06','1','來自明朝')
|
3.3.2.2. 配置映射文件
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
<insert
id="insertUser"
parameterType="cn.itheima.mybatis.po.User">
insert into `user`(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
|
3.3.2.3. 編寫測試代碼
// 3.測試新增用戶
@Test
public
void
insertUserTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
sqlSessionFactory.openSession();
// 2.使用sqlSession對象,調用方法執行
// insert方法:新增記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
// 創建用戶對象
User user =
new User();
user.setId(3);
user.setUsername("林詩音");
user.setBirthday(new
Date());
user.setSex("2");
user.setAddress("來自大明朝");
sqlSession.insert("test.insertUser",
user);
// 3.釋放資源
sqlSession.close();
}
|
問題:java程序執行成功,但是數據庫中並沒有林詩音的數據,原因是沒有提交事務。
3.3.2.4. 提交事務
3.3.2.4.1. 方式一
// 3.測試新增用戶
@Test
public
void
insertUserTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
sqlSessionFactory.openSession();
// 2.使用sqlSession對象,調用方法執行
// insert方法:新增記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
// 創建用戶對象
User user =
new User();
user.setId(3);
user.setUsername("林詩音");
user.setBirthday(new
Date());
user.setSex("2");
user.setAddress("來自大明朝");
sqlSession.insert("test.insertUser",
user);
// 數據庫提交事務:commit
sqlSession.commit();
// 3.釋放資源
sqlSession.close();
}
|
3.3.2.4.2. 方式二
// 3.測試新增用戶
@Test
public
void
insertUserTest(){
// 1.創建sqlSession對象
//SqlSession sqlSession = sqlSessionFactory.openSession();
// 創建sqlSession對象,指定自動提交事務。true:表示提交;false:表示不提交。默認是false
SqlSession sqlSession =
this.sqlSessionFactory.openSession(true);
// 2.使用sqlSession對象,調用方法執行
// insert方法:新增記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
// 創建用戶對象
User user =
new User();
user.setId(4);
user.setUsername("林詩音");
user.setBirthday(new
Date());
user.setSex("2");
user.setAddress("來自大明朝");
sqlSession.insert("test.insertUser",
user);
// 數據庫提交事務:commit
//sqlSession.commit();
// 3.釋放資源
sqlSession.close();
}
|
問題:用戶表中id是自增長,不需要傳遞,但是mybatis中如何獲取到新增以後的用戶Id???
mysql數據庫查詢新增Id:
select LAST_INSERT_ID()
3.3.2.5. 獲取新增的用戶Id
3.3.2.5.1. 方式一
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
<insert
id="insertUser"
parameterType="cn.itheima.mybatis.po.User">
<!-- insert into `user`(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
-->
<!-- selectKey標籤:查詢主鍵id,說明
keyColumn屬性:主鍵字段(表)
keyProperty屬性:主鍵屬性(pojo)
resultType屬性:指定主鍵字段類型
order屬性:指定在insert語句之前,還是之後獲取主鍵值.
BEFORE:在insert語句前;AFTER:在insert語句之後-->
<selectKey keyColumn="id"
keyProperty="id" resultType="int"
order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into `user`(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
|
3.3.2.5.2. 方式二
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
<insert
id="insertUser"
parameterType="cn.itheima.mybatis.po.User"
useGeneratedKeys="true"
keyColumn="id" keyProperty="id">
<!-- insert into `user`(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
-->
<!-- selectKey標籤:查詢主鍵id,說明
keyColumn屬性:主鍵字段(表)
keyProperty屬性:主鍵屬性(pojo)
resultType屬性:指定主鍵字段類型
order屬性:指定在insert語句之前,還是之後獲取主鍵值.
BEFORE:在insert語句前;AFTER:在insert語句之後-->
<!-- <selectKey keyColumn="id" keyProperty="id" resultType="int"
order="AFTER">
select LAST_INSERT_ID()
</selectKey> -->
insert into `user`(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
|
3.3.3.
根據用戶Id修改用戶
3.3.3.1. 準備sql語句
update `user` set username='小李飛刀和林詩音',sex='2'
where id=2
|
3.3.3.2. 配置映射文件
<!-- 根據用戶id修改用戶,說明:
update標籤:用於放置修改sql語句-->
<update
id="updateUserById"
parameterType="cn.itheima.mybatis.po.User">
update `user`
set
username=#{username},sex=#{sex}
where id=#{id}
</update>
|
3.3.3.3. 編寫測試代碼
// 4.測試根據用戶Id修改用戶
@Test
public
void
updateUserByIdTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession(true);
// 2.使用sqlSession對象,調用方法執行
// update方法:修改記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
// 創建用戶對象
User user =
new User();
user.setId(3);
user.setUsername("林詩音和小李飛刀");
user.setSex("1");
sqlSession.update("test.updateUserById",
user);
// 3.釋放資源
sqlSession.close();
}
|
3.3.4.
根據用戶Id刪除用戶
3.3.4.1. 準備sql語句
delete from `user` where id=4
|
3.3.4.2. 配置映射文件
<!-- 根據用戶id刪除用戶,說明:
delete標籤:用於放置刪除的sql語句-->
<delete
id="deleteUserById"
parameterType="int">
delete from `user` where id=#{id}
</delete>
|
3.3.4.3. 編寫測試代碼
// 5.測試根據用戶Id刪除用戶
@Test
public
void
deleteUserByIdTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession(true);
// 2.使用sqlSession對象,調用方法執行
// delete方法:刪除記錄
// statement參數:執行的sql語句(名稱空間+sql語句Id)
// parameter參數:傳入的參數值
sqlSession.delete("test.deleteUserById",
35);
// 3.釋放資源
sqlSession.close();
}
|
4.
mybatis框架原理
1.
Configuration配置對象:sqlMapConfig.xl,User.xml......
2.
MappedStatement對象:負責輸入輸出映射,ParameterType參數輸入,ResultType返回值輸出
3.
Executor執行器對象:負責執行數據庫的CRUD操作
5.
mybatis兩種開發方法
1.
原始的dao開發方法
2.
mapper代理開發方法
5.1.
原始的dao開發方法
5.1.1.
需求
1.
根據用戶Id查詢用戶
2.
新增用戶
5.1.2.
需求實現
5.1.2.1. 準備用戶dao接口
public
interface UserDao {
// 1.根據用戶Id查詢用戶
User queryUserById(Integer id);
// 2.新增用戶
void
insertUser(User user);
}
|
5.1.2.2. 實現用戶dao接口
public
class UserDaoImpl
implements UserDao {
// 定義sqlSessionFactory對象
private
SqlSessionFactory sqlSessionFactory;
/**
*
*/
public
UserDaoImpl() {
super();
}
/**
*
@param sqlSessionFactory
*/
public
UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory
= sqlSessionFactory;
}
/* (non-Javadoc)
* @see cn.itheima.mybatis.dao.UserDao#queryUserById(java.lang.Integer)
*/
public
User queryUserById(Integer id) {
//
TODO Auto-generated
method stub
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession();
// 2.使用sqlSession對象,調用方法執行
Object user = sqlSession.selectOne("test.queryUserById",
id);
// 3.釋放資源
sqlSession.close();
return (User) user;
}
/* (non-Javadoc)
* @see cn.itheima.mybatis.dao.UserDao#insertUser(cn.itheima.mybatis.po.User)
*/
public
void insertUser(User user)
{
//
TODO Auto-generated
method stub
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession(true);
// 2.使用sqlSession對象,調用方法執行
sqlSession.insert("test.insertUser",
user);
// 3.釋放資源
sqlSession.close();
}
}
|
5.1.2.3. 編寫測試代碼
public
class UserDaoTest {
private
SqlSessionFactory sqlSessionFactory =
null;
@Before
public
void init()
throws IOException{
// 1.加載核心配置文件:sqlMapConfig.xml
// resource屬性:指定核心配置文件位置
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.讀取配置文件內容
SqlSessionFactoryBuilder builder =
new SqlSessionFactoryBuilder();
// SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
sqlSessionFactory = builder.build(inputStream);
}
// 測試根據用戶Id查詢用戶
@Test
public
void queryUserByIdTest(){
// 1.創建用戶dao對象
UserDao userDao =
new UserDaoImpl(sqlSessionFactory);
// 2.使用userDao對象,調用方法執行
User user = userDao.queryUserById(2);
System.out.println(user);
}
}
|
測試新增用戶:
// 測試新增用戶
@Test
public
void
insertUserTest(){
// 1.創建用戶dao對象
UserDao userDao =
new UserDaoImpl(sqlSessionFactory);
// 2.使用userDao對象,調用方法執行
// 創建用戶對象
User user =
new User();
user.setUsername("阿飛");
user.setSex("1");
user.setBirthday(new
Date());
user.setAddress("來自大明朝");
System.out.println("執行前:"+user);
userDao.insertUser(user);
System.out.println("執行後:"+user);
}
|
5.2. mapper代理開發方法
5.2.1.
注意事項
1.
要求mapper映射文件中namespace屬性值,必須是mapper接口的全路徑(包名稱+接口名稱)
2.
要求mapper映射文件中sql語句的聲明,與mapper接口方法的聲明一致
2.1.mapper接口返回值類型,與sql語句標籤的resultType屬性指定的類型一致
2.2.mapper接口的方法名稱,與sql語句id屬性值一致
2.3.mapper接口的方法的形參,與sql語句的parameterType屬性指定的類型一致
5.2.2.
需求
1.
根據用戶Id查詢用戶
2.
新增用戶
5.2.3.
需求實現
5.2.3.1. 準備用戶mapper接口
public
interface UserMapper {
// 1.根據用戶Id查詢用戶
User queryUserById(Integer id);
// 2.新增用戶
void
insertUser(User user);
}
|
5.2.3.2. 準備用戶mapper映射文件
<?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屬性:名稱空間,相當於java中的package,用於放置sql語句衝突
-->
<!--mapper代理開發方法中,namespace屬性值,必須是mapper接口的全路徑
-->
<mapper
namespace="cn.itheima.mybatis.mapper.UserMapper">
<!-- 根據用戶Id查詢用戶,說明:
select標籤:用於放置查詢sql語句
id屬性:唯一標識一條sql語句
parameterType屬性:輸入參數類型
resultType屬性:返回值類型
#{id}:佔位符,相當於jdbc中的問號:?-->
<select
id="queryUserById"
parameterType="int"
resultType="cn.itheima.mybatis.po.User">
select * from `user` where id=#{id}
</select>
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
<insert
id="insertUser"
parameterType="cn.itheima.mybatis.po.User"
useGeneratedKeys="true"
keyColumn="id"
keyProperty="id">
insert into `user`(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
|
5.2.3.3. 在sqlMapConfig.xml,加載UserMapper.xml文件
<!-- 加載mapper映射文件
-->
<mappers>
<!--加載User.xml文件,說明:
resource屬性:指定配置文件的位置-->
<mapper
resource="sqlmap/User.xml"/>
<!-- 加載UserMapper.xml文件 -->
<mapper resource="sqlmap/UserMapper.xml"/>
</mappers>
|
5.2.3.4. 編寫測試代碼
public
class UserMapperTest {
private
SqlSessionFactory sqlSessionFactory =
null;
@Before
public
void init()
throws IOException{
// 1.加載核心配置文件:sqlMapConfig.xml
// resource屬性:指定核心配置文件位置
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.讀取配置文件內容
SqlSessionFactoryBuilder builder =
new SqlSessionFactoryBuilder();
// SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
sqlSessionFactory = builder.build(inputStream);
}
// 測試根據用戶Id查詢用戶
@Test
public
void queryUserByIdTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession();
// 2.使用sqlSession對象,獲取mapper代理對象
// getMapper方法:獲取mapper代理對象
// type參數:mapper接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3.使用mapper代理對象,調用方法執行
User user = mapper.queryUserById(2);
System.out.println(user);
// 4.釋放資源
sqlSession.close();
}
}
|
測試新增用戶:
// 測試新增用戶
@Test
public
void
insertUserTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession(true);
// 2.使用sqlSession對象,獲取mapper代理對象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3.使用mapper對象,調用方法執行
// 創建用戶對象
User user =
new User();
user.setUsername("天機老人");
user.setSex("1");
user.setBirthday(new
Date());
user.setAddress("來自大明朝");
mapper.insertUser(user);
// 4.釋放資源
sqlSession.close();
}
|
5.3.
兩種開發方法總結
1.
原始的dao開發方法:需要開發接口和實現類
2.
mapper代理開發方法:只需要開發接口
3.
企業項目中,推薦使用mapper代理開發
6.
mybatis核心配置文件
sqlMapConfig.xml:配置運行環境(數據源),mapper映射文件。
順序
|
配置標籤名稱
|
說明
|
1
|
properties
|
屬性
|
2
|
settings
|
配置全局參數
|
3
|
typeAliases
|
類型別名
|
4
|
typeHandlers
|
類型處理器
|
5
|
objectFactory
|
對象工廠
|
6
|
plugins
|
插件
|
7
|
environments
|
環境集合屬性對象
|
8
|
databaseIdProvider
|
多數據庫支持
|
9
|
mappers
|
映射器
|
說明:
1.
紅色字體內容要求掌握
2.
在sqlMapConfig.xml中必須是從上往下的配置順序
|
6.1. properties(屬性)
作用:加載屬性文件(比如db.properties)和定義屬性
6.1.1.
準備db.properties文件
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/mybatis
db.username=root
db.password=admin
|
6.1.2.
加載db.properties屬性文件
<!--加載屬性文件,說明:
1.resource屬性:指定本地配置文件的位置
2.url屬性:指定網絡上的配置文件位置-->
<properties
resource="db.properties"
>
</properties>
|
6.1.3.
使用db.propertis屬性文件中的屬性
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments
default="development">
<!-- id屬性:唯一標識一個運行環境 -->
<environment
id="development">
<!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務
-->
<transactionManager
type="JDBC"
/>
<!-- 數據源配置,POOLED:mybatis提供的連接池 -->
<dataSource
type="POOLED">
<!-- <property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/mybatis"
/>
<property name="username"
value="root" />
<property name="password" value="admin"
/> -->
<!-- 使用db.properties屬性文件的屬性 -->
<property name="driver"
value="${db.driver}" />
<property name="url"
value="${db.url}" />
<property name="username"
value="${db.username}" />
<property name="password"
value="${db.password}" />
</dataSource>
</environment>
</environments>
|
6.1.4.
使用內部property標籤定義屬性
<!--加載屬性文件,說明:
1.resource屬性:指定本地配置文件的位置
2.url屬性:指定網絡上的配置文件位置
3.使用內部property標籤定義屬性
4.加載順序:首先加載內部property標籤定義的屬性,再加載屬性文件中的屬性,
如果有相同的屬性,屬性文件中的屬性,覆蓋內部property標籤的屬性-->
<properties
resource="db.properties"
>
<property
name="db.username"
value="root123"/>
<property
name="db.password"
value="admin"/>
</properties>
|
6.2. typeAliases(類型別名)
作用:簡稱。比如中華人民共和國,簡稱中國。
6.2.1.
內置別名
別名
|
映射類型
|
_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
|
object
|
Object
|
map
|
Map
|
hashmap
|
HashMap
|
list
|
List
|
arraylist
|
ArrayList
|
collection
|
Collection
|
iterator
|
Iterator
|
說明:
1.
內置別名可以直接使用
2.
別名不區分大小寫
6.2.2.
自定義別名
6.2.2.1. 自定義別名方式一
<!-- 自定義別名配置 -->
<typeAliases>
<!-- 自定義用戶別名配置,說明:
1.type屬性:別名的類型
2.默認使用類名稱,作爲別名
3.alias屬性:指定別名的名稱 -->
<typeAlias
type="cn.itheima.mybatis.po.User"
alias="user"/>
</typeAliases>
|
6.2.2.2. 自定義別名方式二
<!-- 自定義別名配置 -->
<typeAliases>
<!-- 自定義用戶別名配置,說明:
1.type屬性:別名的類型
2.默認使用類名稱,作爲別名
3.alias屬性:指定別名的名稱 -->
<!-- <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/> -->
<!--包掃描方式配置別名,說明:
1.name屬性:指定掃描的包
2.默認使用類名稱,作爲別名
3.如果有多個包,配置多個package
4.企業項目中,推薦使用包掃描方式 -->
<package name="cn.itheima.mybatis.po"/>
</typeAliases>
|
6.3. mappers(映射器)
作用:加載mapper映射文件。
6.3.1.
加載mapper映射文件方式一
<!-- 加載mapper映射文件
-->
<mappers>
<!--加載User.xml文件,說明:
resource屬性:指定配置文件的位置-->
<mapper
resource="sqlmap/User.xml"/>
<!-- 加載UserMapper.xml文件 -->
<mapper
resource="sqlmap/UserMapper.xml"/>
</mappers>
|
6.3.2.
加載mapper映射文件方式二
<!-- 加載mapper映射文件
-->
<mappers>
<!--加載User.xml文件,說明:
resource屬性:指定配置文件的位置-->
<mapper
resource="sqlmap/User.xml"/>
<!-- 加載UserMapper.xml文件 -->
<!-- <mapper resource="sqlmap/UserMapper.xml"/>
-->
<!-- 包掃描方式加載mapper映射文件,說明:
1.前提必須是mapper代理開發方法
2.要求mapper映射文件,與mapper接口在同一個目錄
3.要求mapper映射文件的名稱,與mapper接口的名稱一致
-->
<package name="cn.itheima.mybatis.mapper"/>
</mappers>
|
7.
mybatis與hibernate比較
7.1.
相同點
都是對jdbc的封裝,都是持久層的框架,都用於dao層的開發。
7.2.
不同點
1.
hibernate是對sql語句做了封裝,提供HQL語言操作數據庫,數據庫無關性支持好,在項目需要支持多種數據庫的情況下,代碼開發量較少,sql語句優化困難;mybatis是直接使用sql語句操作數據庫,不支持數據庫無關性,在項目需要支持多種數據庫的情況下,代碼開發量較多,sql語句優化容易。
2.
hibernate是配置java對象與數據庫表的對應關係,多表關聯關係配置複雜。mybatis是配置java對象,與sql語句對應關係,多表關聯關係配置容易。
3.
hibernate是重量級的框架,學習使用門檻高,適合於需求相對穩定,中小型的項目,比如:辦公自動化系統(OA);mybatis是輕量級的框架,學習使用門檻低,適合於需求變化頻繁,大型的項目,比如:互聯網電子商務網站項目。目前在企業項目中,mybatis框架使用更多一些。
8.
擴展
8.1.
註解開發
// 3.根據用戶Id查詢用戶,使用註解開發實現
@Select("select
* from `user` where id=#{id}")
User queryUserById_1(Integer id);
|
// 測試根據用戶Id查詢用戶,測試註解開發
@Test
public
void queryUserById_1Test(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession();
// 2.使用sqlSession對象,獲取mapper代理對象
// getMapper方法:獲取mapper代理對象
// type參數:mapper接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3.使用mapper代理對象,調用方法執行
User user = mapper.queryUserById_1(2);
System.out.println(user);
// 4.釋放資源
sqlSession.close();
}
|
說明:註解開發,只做瞭解,企業項目中不推薦使用。
8.2.
緩存
8.2.1.
一級緩存(sqlSession級別)
// 測試根據用戶Id查詢用戶,測試一級緩存
@Test
public
void
oneCacheTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession();
// 2.使用sqlSession對象,獲取mapper代理對象
// getMapper方法:獲取mapper代理對象
// type參數:mapper接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3.使用mapper代理對象,調用方法執行
User user = mapper.queryUserById(2);
System.out.println(user);
System.out.println("-------------------------------------");
User user1 = mapper.queryUserById(2);
System.out.println(user1);
// 4.釋放資源
sqlSession.close();
}
|
說明:一級緩存mybatis框架就已經默認使用,不需要關心。
8.2.2.
二級緩存(mapper級別緩存,在多個SqlSession之間共享)
8.2.2.1. 在sqlMapConfig.xml中,配置開啓二級緩存
<!-- 全局參數配置 -->
<settings>
<!-- 配置開啓二級緩存 -->
<setting
name="cacheEnabled"
value="true"/>
</settings>
|
8.2.2.2. 修改用戶pojo,實現序列化接口
public
class
User
implements
java.io.Serializable{
private Integer
id;
//
int(11) NOT NULL AUTO_INCREMENT,
private String
username;
//
varchar(32) NOT NULL COMMENT '用戶名稱',
private Date
birthday;
// date DEFAULT NULL COMMENT '生日',
private String
sex;
// char(1) DEFAULT NULL COMMENT '性別',
private String
address;
//
varchar(256) DEFAULT NULL COMMENT '地址',
|
8.2.2.3. 在UserMapper.xml中,開啓使用二級緩存
8.2.2.4. 測試二級緩存
// 測試根據用戶Id查詢用戶,測試二級緩存
@Test
public
void twoCacheTest(){
// 1.創建sqlSession對象
SqlSession sqlSession =
this.sqlSessionFactory.openSession();
// 2.使用sqlSession對象,獲取mapper代理對象
// getMapper方法:獲取mapper代理對象
// type參數:mapper接口的class
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 3.使用mapper代理對象,調用方法執行
User user = mapper.queryUserById(2);
System.out.println(user);
// 4.釋放資源
sqlSession.close();
System.out.println("-----------------------------------------");
// 5.創建sqlSession對象
SqlSession sqlSession1 =
this.sqlSessionFactory.openSession();
// 6.使用sqlSession對象,獲取mapper代理對象
// getMapper方法:獲取mapper代理對象
// type參數:mapper接口的class
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
// 7.使用mapper代理對象,調用方法執行
User user1 = mapper1.queryUserById(2);
System.out.println(user1);
// 8.釋放資源
sqlSession1.close();
}
說明:mybatis框架的二級緩存,只做瞭解,企業項目中不推薦使用。原因是mybatis框架的二級緩存不能實現細粒度的控制。
|