摘要:解決方法使用數據庫連接池管理數據庫連接。向中設置參數,對占位符號位置和設置參數值,硬編碼在代碼中,同樣也不利于系統的維護。從中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼,不利于系統維護。
Mybatis
Mybatis 和 SpringMVC 通過訂單商品案例驅動
官方中文地址:http://www.mybatis.org/mybati...
官方托管地址:https://github.com/mybatis/my...
本項目全部代碼地址:https://github.com/zhisheng17...
文章首發地址:http://blog.csdn.net/tzs_1041...
基礎知識: 對原生態 jdbc 程序(多帶帶使用 jdbc 開發)問題總結 1、環境? java 環境 :jdk1.8.0_77
? 開發工具 : IDEA 2016.1
? 數據庫 : MySQL 5.7
2、創建數據庫? mybatis_test.sql
? Tables :items、orderdetail、orders、user
3、JDBC 程序? 使用 JDBC 查詢 MySQL 數據庫中用戶表的記錄
? 代碼:
package cn.zhisheng.mybatis.jdbc; /** * Created by 10412 on 2016/11/27. */ import java.sql.*; /** *通過多帶帶的jdbc程序來總結問題 */ public class JdbcTest { public static void main(String[] args) { //數據庫連接 Connection connection = null; //預編譯的Statement,使用預編譯的Statement可以提高數據庫性能 PreparedStatement preparedStatement = null; //結果集 ResultSet resultSet = null; try { //加載數據庫驅動 Class.forName("com.mysql.jdbc.Driver"); //通過驅動管理類獲取數據庫鏈接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_test?characterEncoding=utf-8", "root", "root"); //定義sql語句 ?表示占位符(在這里表示username) 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(); } } } } }4、問題總結
Mybatis框架原理(掌握) 1、Mybatis 是什么?數據庫連接,使用時就創建,不使用立即釋放,對數據庫頻繁連接開啟和關閉,造成數據庫資源的浪費,影響數據庫性能。
解決方法:使用數據庫連接池管理數據庫連接。
將 sql 語句硬編碼到 java 代碼中,如果 sql 語句需要修改,那么就需要重新編譯 java 代碼,不利于系統的維護。
設想:將 sql 語句配置在 xml 配置文件中,即使 sql 語句發生變化,也不需要重新編譯 java 代碼。
向 preparedStatement 中設置參數,對占位符號位置和設置參數值,硬編碼在 java 代碼中,同樣也不利于系統的維護。
設想:將 sql 語句、占位符、參數值配置在 xml 配置文件中。
從 resultSet 中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼,不利于系統維護。
設想:將查詢的結果集自動映射成 java 對象。
? Mybatis 是一個持久層的架構,是 appach 下的頂級項目。
? Mybatis 原先是托管在 googlecode 下,再后來是托管在 Github 上。
? Mybatis 讓程序員將主要的精力放在 sql 上,通過 Mybatis 提供的映射方式,自由靈活生成(半自動,大部分需要程序員編寫 sql )滿足需要 sql 語句。
? Mybatis 可以將向 preparedStatement 中的輸入參數自動進行輸入映射,將查詢結果集靈活的映射成 java 對象。(輸出映射)
2、Mybatis 框架注解:
Mybatis入門程序 1、需求SqlMapConfig.xml (Mybatis的全局配置文件,名稱不定)配置了數據源、事務等 Mybatis 運行環境
Mapper.xml 映射文件(配置 sql 語句)
SqlSessionFactory (會話工廠)根據配置文件配置工廠、創建 SqlSession
SqlSession (會話)面向用戶的接口、操作數據庫(發出 sql 增刪改查)
Executor (執行器)是一個接口(基本執行器、緩存執行器)、SqlSession 內部通過執行器操作數據庫
Mapped Statement (底層封裝對象)對操作數據庫存儲封裝,包括 sql 語句、輸入參數、輸出結果類型
?
實現以下功能:
2、環境根據用戶id查詢一個用戶信息
根據用戶名稱模糊查詢用戶信息列表
添加用戶
更新用戶
刪除用戶
java 環境 :jdk1.8.0_77
開發工具 : IDEA 2016.1
數據庫 : MySQL 5.7
Mybatis 運行環境( jar 包)
MySQL 驅動包
其他依賴包
3、 log4j.properties在classpath下創建log4j.properties如下:
# Global logging configuration #在開發環境日志級別要設置為DEBUG、生產環境要設置為INFO或者ERROR 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
Mybatis默認使用log4j作為輸出日志信息。
4、工程結構 5、SqlMapConfig.xml配置 Mybatis 的運行環境、數據源、事務等
6、創建 po 類
Po 類作為 mybatis 進行 sql 映射使用,po 類通常與數據庫表對應,User.java 如下:
package cn.zhisheng.mybatis.po; import java.util.Date; /** * Created by 10412 on 2016/11/28. */ public class User { private int id; private String username; // 用戶姓名 private String sex; // 性別 private Date birthday; // 生日 private String address; // 地址 //getter and setter 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }7、根據用戶 id(主鍵)查詢用戶信息
映射文件
User.xml(原在 Ibatis 中命名)在 Mybatis 中命名規則為 xxxmapper.xml
在映射文件中配置 sql 語句
User.xml
namespace :命名空間,對 sql 進行分類化管理,用于隔離 sql 語句,后面會講另一層非常重要的作用。
?
在 User.xml 中加入
User.xml 映射文件已經完全寫好了,那接下來就需要在 SqlMapConfig.xml中加載映射文件 User.xml
?
編寫程序
`MybatisFirst.java` ?
package cn.zhisheng.mybatis.first; import cn.zhisheng.mybatis.po.User; 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.Test; import java.io.IOException; import java.io.InputStream; /** * Created by 10412 on 2016/11/28. */ public class MybatisFirst { //根據id查詢用戶信息,得到用戶的一條記錄 @Test public void findUserByIdTest() throws IOException { //Mybatis 配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入Mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //通過SqlSession操作數據庫 //第一個參數:映射文件中Statement的id,等于 = namespace + "." + Statement的id //第二個參數:指定和映射文件中所匹配的parameterType類型的參數 //sqlSession.selectOne 結果與映射文件中所匹配的resultType類型的對象 User user = sqlSession.selectOne("test.findUserById", 1); System.out.println(user); //釋放資源 sqlSession.close(); } }
然后運行一下這個測試,發現結果如下就代表可以了:
8、根據用戶名稱模糊查詢用戶信息列表映射文件
依舊使用 User.xml 文件,只不過要在原來的文件中加入
編寫程序
依舊直接在剛才那個 MybatisFirst.java 中加入測試代碼:
//根據用戶名稱模糊查詢用戶信息列表 @Test public void findUserByUsernameTest() throws IOException { //Mybatis 配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入Mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //通過SqlSession操作數據庫 //第一個參數:映射文件中Statement的id,等于 = namespace + "." + Statement的id //第二個參數:指定和映射文件中所匹配的parameterType類型的參數 //selectList 查詢結果可能多條 //list中的user和映射文件中resultType所指定的類型一致 Listlist = sqlSession.selectList("test.findUserByUsername", "小明"); System.out.println(list); //釋放資源 sqlSession.close(); }
同樣測試一下findUserByUsernameTest ,如果運行結果如下就代表沒問題:
提示:通過這個代碼可以發現,其中有一部分代碼是冗余的,我們可以將其封裝成一個函數。
public void createSqlSessionFactory() throws IOException { // 配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 使用SqlSessionFactoryBuilder從xml配置文件中創建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }注意: 1、#{ } 和 ${ } 的區別
2、parameterType 和 resultType 區別#{ }表示一個占位符號,通過#{ }可以實現 preparedStatement 向占位符中設置值,自動進行java 類型和 jdbc 類型轉換,#{ } 可以有效防止sql注入。#{ } 可以接收簡單類型值或 pojo 屬性值(通過 OGNL 讀取對象中的值,屬性.屬性.屬性..方式獲取對象屬性值)。 如果 parameterType 傳輸單個簡單類型值,#{ } 括號中可以是 value 或其它名稱。
${ } 表示拼接 sql 串,通過${ }可以將 parameterType 傳入的內容拼接在 sql 中且不進行 jdbc 類型轉換, ${ }可以接收簡單類型值或 pojo 屬性值((通過 OGNL 讀取對象中的值,屬性.屬性.屬性..方式獲取對象屬性值)),如果 parameterType 傳輸單個簡單類型值,${}括號中只能是 value。
3、selectOne 和 selectList 區別parameterType:指定輸入參數類型,mybatis 通過 ognl 從輸入對象中獲取參數值拼接在 sql 中。
resultType:指定輸出結果類型,mybatis 將 sql 查詢結果的一行記錄數據映射為 resultType 指定類型的對象。
9、添加用戶selectOne 查詢一條記錄來進行映射,如果使用selectOne查詢多條記錄則拋出異常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to bereturned by selectOne(), but found: 3 at
selectList 可以查詢一條或多條記錄來進行映射。
映射文件
在 User.xml 中加入:
select LAST_INSERT_ID() insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
注意:
selectKey將主鍵返回,需要再返回
添加selectKey實現將主鍵返回
keyProperty:返回的主鍵存儲在pojo中的哪個屬性
order:selectKey的執行順序,是相對與insert語句來說,由于mysql的自增原理執行完insert語句之后才將主鍵生成,所以這里selectKey的執行順序為after
resultType:返回的主鍵是什么類型
LAST_INSERT_ID():是mysql的函數,返回auto_increment自增列新記錄id值。
然后在 MybatisFirst.java 中寫一個測試函數,代碼如下
@Test public void insetrUser() throws IOException, ParseException { //Mybatis 配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入Mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User(); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd"); user.setUsername("田志聲"); user.setSex("男"); user.setBirthday(sdf.parse("2016-11-29")); user.setAddress("江西南昌"); sqlSession.insert("test.insetrUser", user); sqlSession.commit(); //釋放資源 sqlSession.close(); }
然后 run 一下,如果出現的結果如下,那么就是成功了。
同時數據庫也能查詢到剛插入的用戶信息:
10、自增主鍵返回 與 非自增主鍵返回MySQL 自增主鍵:執行 insert 提交之前自動生成一個自增主鍵,通過 MySQL 函數獲取到剛插入記錄的自增主鍵: LAST_INSERT_ID() ,是在 insert 函數之后調用。
非自增主鍵返回:使用 MySQL 的 uuid() 函數生成主鍵,需要修改表中 id 字段類型為 String ,長度設置為 35 位,執行思路:先通過 uuid() 查詢到主鍵,將主鍵輸入到 sql 語句中;執行 uuid() 語句順序相對于 insert 語句之前執行。
剛才那個插入用戶的地方,其實也可以通過 uuid() 來生成主鍵,如果是這樣的話,那么我們就需要在 User.xml 中加入如下代碼:
select uuid() insert into user(id, username, birthday, sex, address) values(#{id}, #{username}, #{birthday}, #{sex}, #{address})
Oracle 使用序列生成主鍵
首先自定義一個序列且用于生成主鍵,selectKey使用如下:
SELECT 自定義序列.NEXTVAL FROM DUAL insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
?
11、刪除用戶前面說了這么多了,這里就簡單來說明下:
在 User.xml 文件中加入如下代碼:
delete from user where user.id = #{id}
在 MybatisFirst.java 文件中加入如下代碼:
//刪除用戶 @Test public void deleteUserByIdTest() throws IOException { //Mybatis 配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入Mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //通過SqlSession操作數據庫 //第一個參數:映射文件中Statement的id,等于 = namespace + "." + Statement的id //第二個參數:指定和映射文件中所匹配的parameterType類型的參數 sqlSession.delete("test.deleteUserById", 26); //提交事務 sqlSession.commit(); //釋放資源 sqlSession.close(); }
測試結果如下:
之前的數據庫 user 表查詢結果:
執行完測試代碼后,結果如下:
12、更新用戶信息在 User.xml 中加入如下代碼:
update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where user.id = #{id}
然后在 MybatisFirst.java 中加入
//根據id更新用戶信息 @Test public void updateUserByIdTest() throws IOException, ParseException { //Mybatis 配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠,傳入Mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //為了設置生日的日期輸入 SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd"); User user = new User(); //根據id更新用戶信息 user.setId(24); user.setUsername("張四風"); user.setBirthday(sdf.parse("2015-01-12")); user.setSex("女"); user.setAddress("上海黃埔"); //通過SqlSession操作數據庫 //第一個參數:映射文件中Statement的id,等于 = namespace + "." + Statement的id //第二個參數:指定和映射文件中所匹配的parameterType類型的參數 sqlSession.update("test.updateUserById", user); //提交事務 sqlSession.commit(); //釋放資源 sqlSession.close(); }
測試結果如下:
查看數據庫,id 為 24 的用戶信息是否更新了:
啊,是不是很爽,所有的需求都完成了。
沒錯,這只是 Mybatis 的一個簡單的入門程序,簡單的實現了對數據庫的增刪改查功能,通過這個我們大概可以了解這個編程方式了。
期待接下來的 Mybatis高級知識文章吧!
更多文章請見 微信公眾號:猿blog
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66269.html
摘要:場合常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用將每一條記錄映射到中,在前端頁面遍歷中是即可。作用將關聯查詢信息映射到一個對象中。 相關閱讀: 1、通過項目逐步深入了解Mybatis 2、 通過項目逐步深入了解Mybatis 本項目所有代碼及文檔都托管在 Github地址:https://github.com/zhisheng17/myb...
摘要:的實例不能共享使用,它也是線程不安全的。因此最佳的范圍是請求或方法范圍定義局部變量使用。在中就不需要直接對數據庫的連接參數進行硬編碼了。 轉載請務必注明出處,原創不易! 相關文章:通過項目逐步深入了解Mybatis 本項目全部代碼地址:Github-Mybatis Mybatis 解決 jdbc 編程的問題 1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用...
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
閱讀 2411·2021-11-25 09:43
閱讀 1246·2021-11-24 09:39
閱讀 742·2021-11-23 09:51
閱讀 2382·2021-09-07 10:18
閱讀 1841·2021-09-01 11:39
閱讀 2776·2019-08-30 15:52
閱讀 2589·2019-08-30 14:21
閱讀 2850·2019-08-29 16:57