MyBatis流程圖
一、傳統的JDBC編程過程
加載驅動、獲取connection、創建Statement預編譯對象、編寫sql語句、佔位符設值、執行sql,並返回結果、對sql結果進行解析、釋放資源。
存在的問題:
加載驅動、獲取connection、釋放資源等過程過於頻繁,影響性能而且造成資源的浪費。
Statement對象的sql設置參數、sql語句存在硬編碼問題,造成代碼不易維護。
對結果集的封裝也存在硬編碼問題。
二、mybatis框架
mybatis是apache的一個開源項目GitHub;
是一個優秀的持久化層框架。相當於架構中Dao層,對JDBC的操作過程進行了封裝,是的開發者只需關注sql本身,而不需要去處理,例如:加載驅動、獲取鏈接、創建Statement對象、結果集封裝、資源釋放等過程。
三、mybatis的架構
**.xml全局配置文件,配置了mybatis的運行環境信息。
配置了映射文件:–>編寫sql語句 文件格式*Mapper.xml
SqlSessionFactory:會話工廠。通過全局配置文件加載生成。功能:創建會話,SqlSession
SqlSession:會話。作用:操作數據庫中的椅一些增刪改查。是一個接口。
Executor執行器:SqlSession通過執行器進行的操作數據庫。
mappedStatement:底層封裝對象。作用:對數據庫的操作過程進行封裝,包括sql語句、輸入參數、輸出結果;
輸入參數的類型:java基本類型、自定義的pojo對象、hashMap
輸出結果的類型:Java基本類型,自定義的pojo對象,hashMap
配置全局文件
<?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:默認要加載的環境
當mybatis與spring整合後,以下配置將廢除不需要了
-->
<environments default="mysql">
<environment id="mysql">
<!-- 事務管理的配置 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 數據庫鏈接池 -->
<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>
<!-- 配置加載的映射文件 -->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
這裏數據庫連接池參數採用的是引用的方式,放置以後頻繁修改參數造成不必要的錯誤
引用的方式
<!-- 讀取資源文件 -->
<properties resource="db.properties"></properties>
<!-- ----------------------------------數據的配置文件--------------------------------------------- -->
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/db_user?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
配置映射文件
對數據庫中標的增刪改查語句都將在映射文件編寫
<?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 namespace="UserMapper">
</mapper>
查詢數據庫中的數據
兩種方式
id:用於標識映射文件的sql , 爲statement的id, 唯一的,不能重複
parameterType:輸入參數的類型 支持的類型:java基礎類型、pojo對象、hashMap
#{}:給佔位符設置值 接收參數裏的參數信息
當參數類型爲基本類型時,#{}裏的參數任意或者是#{value}
resultType:結果集類型 支持的類型:java基礎類型、pojo對象、hashMap,指的是單挑記錄的類型
<!-- 根據id查詢用戶信息 -->
<select id="selectById" parameterType="int" resultType="com.hpe.pojo.User" >
SELECT * FROM user WHERE id = #{id}
</select>
第二種
${}:
字符串拼接,沒有使用佔位符,不安全,有sql注入的風險
如果參數類型爲基本類型則${}
裏面參數只能是${value}
建議不要使用此方式。
模糊查詢時可以在java代碼中直接使用%%
模糊查詢的符號作爲參數傳過去即可
<!-- 根據姓名模糊查詢 -->
<select id="selectByName" parameterType="String" resultType="User" >
SELECT * FROM user WHERE username LIKE <!-- #{value} --> '%${value}%'
</select>
添加
參數類型爲自定義的pojo對象時,取值方式#{屬性}
keyProperty=“id” useGeneratedKeys=“true” 獲取新增數據的id
<!-- 新增用戶 -->
<insert id="addUser" parameterType="User" keyProperty="id" useGeneratedKeys="true">
INSERT INTO user (username,birthday,sex,address) VALUES
(#{username},#{birthday},#{sex},#{address})
</insert>
修改
<!-- 修改用戶 -->
<update id="updateUser" parameterType="User" >
UPDATE user SET username=#{username},address=#{address} WHERE id=#{id}
</update>
刪除
<!-- 刪除用戶 -->
<delete id="deleteUser" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
四、mybatis的核心對象
SqlSessionFactory:會話工廠
由全局配置文件加載,作用創建會話。
特點:一旦創建了會話工廠的實例,那麼在應用程序的執行器都會存在。我們應該把會話工程設計爲單一的實例,單例模式。
SqlSession:會話
由會話工廠創建,作用:創建會話
特點:SqlSession、Servlet都是線程不安全的。調用同一個會話時就會有可能出現問題。
解決方法:把會話聲明成方法內部的局部變量。
五、全局配置文件的一些配置問題
別名的設置
給單個對象起別名 type:給誰起的別名,alias:別名
<typeAliases>
<!-- 給單個對象起別名 type:給誰起別名 alias:別名 -->
<typeAlias type="com.hpe.pojo.User" alias="user"/>
</typeAliases>
批量起別名 name:給哪個包下的類起別名 ,採用的是掃描的方式;別名:類名(首字母大小寫都可以)
<!-- 批量起別名 name:給哪個包下的類起別名 掃描的方式
別名:類名(首字母大小寫都可以)
-->
<package name="com.hpe.pojo" />
Junit測試類
使用junit’測試類需要導入junit-4.9.jar包
現在編寫一個測試方法
@Test
public void testSelectById() throws IOException{
// 1.加載mybatis的全局配置文件 io流的形式
InputStream in = Resources.getResourceAsStream("mybatis.xml");
// 2.獲取會話工廠
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
// 3.獲取會話 通過會話工廠創建,讀取的全局配置文件獲取的
sqlSession = ssf.openSession();
// 4.調用會話的方法進行查詢
// statement:預處理對象-->查詢需要執行的sql語句 -->命名空間+id
// paramter:參數
User user = sqlSession.selectOne("UserMapper.selectById", 1);
System.err.println(user);
sqlSession.close();
}
注意:使用junit測試類方法前必須添加@Test註解符號。
這樣每次編寫代碼時都會編寫重複的代碼,我們可以將重複的代碼提取出來實現代碼的共用。
如:
// 因爲需要在方法中使用會話,所以將SqlSession聲明爲成員變量
SqlSession sqlSession = null;
// @Test之前執行
@Before
public void before() throws IOException{
// 1.加載mybatis的全局配置文件 io流的形式
InputStream in = Resources.getResourceAsStream("mybatis.xml");
// 2.獲取會話工廠
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
// 3.獲取會話 通過會話工廠創建,讀取的全局配置文件獲取的
sqlSession = ssf.openSession();
}
// 根據姓名模糊查詢
@Test
public void selectByName(){
// 調用會話的方法進行查詢
List<User> selectByNameList =
sqlSession.selectList("UserMapper.selectByName", "三");
System.err.println(selectByNameList);
}
// @Test之後執行
@After
public void after(){
sqlSession.close();
}
注意:不要忘記方法前的註解。
還可以將重複的地方寫成一個工具類,在以後再次使用時直接該工具類賦值項目的文件目錄下即可。
如:
private static SqlSessionFactory ssf = null;
// 靜態代碼塊,只加載一次
static{
try {
// 1.加載mybatis的全局配置文件 io流的形式
InputStream in = Resources.getResourceAsStream("mybatis.xml");
// 2.獲取會話工廠
ssf = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* 方法描述:獲取到會話工廠
* @return
*/
public static SqlSessionFactory getFactory() {
return ssf;
}
// 在測試類中的使用
@Test
public void test3() {
// 獲取會話
SqlSession sqlSession = SqlSessionFactoryUtil.getFactory().openSession();
User user = sqlSession.selectOne("UserMapper.selectById", 1);
System.err.println(user);
}