(十三)Golang基礎之指標
1、簡介
1.1、什麼是 MyBatis?
-
MyBatis 是一款優秀的持久層框架
-
它支援自定義 SQL、儲存過程以及高階對映。
-
MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。
-
MyBatis 可以通過簡單的 XML 或註解來配置和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。
-
MyBatis本是apache的一個開源專案iBatis,2010年這個專案由apache software foundation遷移到了google code,並且改名為MyBatis。
-
2013年11月遷移到Github。
如何獲得mybatis?
-
maven倉庫
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
-
1.2、持久化
資料持久化
-
持久化就是將程式的資料在持久狀態和順時狀態轉化的過程
-
記憶體:斷電即失
-
資料庫(JDBC)、io檔案持久化
-
生活:冷藏、罐頭
為什麼需要持久化?
-
有一些物件,不能丟掉
-
記憶體太貴了
-
1.3、持久層
-
Dao層、Service層、controller層
-
完成持久化的程式碼塊
-
層界限十分明顯
-
1.4、為什麼需要MyBatis
-
幫助程式設計師將資料存入資料庫
-
方便
-
傳統的JDBC程式碼太複雜了。簡化。框架。自動化。
-
不用MyBatis也可以,更容易上手。技術沒有高低之分。
-
優點
-
簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar檔案+配置幾個sql對映檔案。易於學習,易於使用。通過文件和原始碼,可以比較完全的掌握它的設計思路和實現。
-
靈活:mybatis不會對應用程式或者資料庫的現有設計強加任何影響。 sql寫在xml裡,便於統一管理和優化。通過sql語句可以滿足操作資料庫的所有需求。
-
解除sql與程式程式碼的耦合:通過提供DAO層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和程式碼的分離,提高了可維護性。
-
提供對映標籤,支援物件與資料庫的orm欄位關係對映。
-
提供物件關係對映標籤,支援物件關係組建維護。
-
提供xml標籤,支援編寫動態sql。
-
最重要得到一點:使用的人多!
2、第一個Mybais程式
思路:搭建環境->匯入mybatis-->編寫程式碼-->測試
2.1、搭建環境
搭建資料庫
create database mybatis;
use mybatis;
create table user(
id int not null primary key auto_increment,
name varchar(30) default null,
pwd varchar(30) default null
);
insert into user values (null,"zhangsan","123456");
insert into user values (null,"lisi","123456");
insert into user values (null,"wangwu","123456");
insert into user values (null,"yueyunpeng","123456");
新建專案
-
新建一個普通的maven專案
-
刪除src目錄
-
匯入Maven依賴
<!--匯入依賴-->
<dependencies>
<!--mysql依賴-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2、建立一個模組
編寫mybatis核心配置檔案
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!--事務管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&userUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
2、編寫mybatis工具類
public class MybatisUtils {
public static SqlSessionFactory sqlSessionFactory = null;
static {
try {
//使用mybatis第一步 獲取sqlSessionFactory物件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,
// 顧名思義,我們可以從中獲得 SqlSession 的例項。
// SqlSession 提供了在資料庫執行 SQL 命令所需的所有方法。
// 你可以通過 SqlSession 例項來直接執行已對映的 SQL 語句。
public static SqlSession getSqlSeesion() {
return sqlSessionFactory.openSession();
}
}
2.3、編寫程式碼
-
實體類
package com.qiang.pojo;
public class User {
private Integer id;
private String name;
private String pwd;
public User() {
}
public User(Integer id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
-
Dao介面
package com.qiang.dao;
import com.qiang.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
-
介面實現類-由原來的的UserDao轉變一個Mapper配置檔案
2.4、測試
可能會遇見的問題:
-
配置檔案沒有註冊
-
繫結介面錯誤
-
方法名不對
-
返回型別不對
-
Maven匯出資源問題
-
public class UserDaoTest {
3、CRUD
1|、namespace
namespace中的包名要和介面的包名一致!
2、select
選擇,查詢語句
-
id:就是對應的namespace中的方法名;
-
resultType:SQL語句執行的返回值!
-
parameterType:引數型別
1、編寫介面
//獲取全部使用者 List<User> getUserList();
2、編寫對應的mapper中的sql語句
<select id="getUserList" resultType="com.qiang.pojo.User"> select * from mybatis.user </select>
3、測試
@Test public void test() { SqlSession sqlSeesion = null; try { //1、獲取SqlSession物件 sqlSeesion = MybatisUtils.getSqlSeesion(); //2、執行sql //3、方式一:getMapper UserMapper mapper = sqlSeesion.getMapper(UserMapper.class); List<User> userList = mapper.getUserList(); // User list = mapper.gerUserById(1); //方式二: // List<User> userList = sqlSeesion.selectList("com.qiang.dao.UserDao.getList"); //System.out.println(list); for (User user : userList) { System.out.println(user); } } finally { sqlSeesion.close(); } }
3、delete
-
編寫介面
//刪除使用者 int deleteUser(int id);
-
編寫對應的mapper中的sql語句
<delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id} </delete>
-
測試
@Test public void test4() { SqlSession sqlSeesion = null; try { sqlSeesion = MybatisUtils.getSqlSeesion(); UserMapper mapper = sqlSeesion.getMapper(UserMapper.class); User user = new User(1, "wuqiang", "123456"); int i = mapper.deleteUser(3); sqlSeesion.commit(); System.out.println(i > 0 ? "刪除成功" : "刪除失敗"); } finally { sqlSeesion.close(); } }
4、update
-
編寫介面
//修改使用者
int updateUser(User user); -
編寫對應的mapper中的sql語句
<update id="updateUser" parameterType="com.qiang.pojo.User">
update mybatis.user set name = #{name},pwd = #{pwd} where id = #{id}
</update> -
測試
5、insert
-
編寫介面
//增加使用者 int addUser(User user);
-
編寫對應的mapper中的sql語句
<insert id="addUser" parameterType="com.qiang.pojo.User" > insert into mybatis.user (id,name,pwd) values(#{id},#{name},#{pwd}) </insert>
-
測試
@Test public void test2() { SqlSession sqlSeesion = null; try { sqlSeesion = MybatisUtils.getSqlSeesion(); UserMapper mapper = sqlSeesion.getMapper(UserMapper.class); User user = new User(null, "aaa", "11111"); int i = mapper.addUser(user); sqlSeesion.commit(); System.out.println(i > 0 ? "新增成功" : "新增失敗"); } finally { sqlSeesion.close(); } }
注意點:
-
增刪改需要提交事務
6、分析錯誤
-
標籤不要匹配錯
-
resource繫結mapper,需要使用路徑
-
程式配置檔案必須符合規範!
7、萬能Map
假設我們得實體類,或者資料庫中的表,欄位或者引數過多,我們應當考慮使用map!
-
編寫介面
//萬能map int addUser2(Map<String,Object> map);
-
編寫對應的mapper中的sql語句
<insert id="addUser2" parameterType="map"> insert into mybatis.user (id,name,pwd) values(#{userId},#{userNamae},#{userPassword}) </insert>
-
測試
@Test public void test5(){ SqlSession sqlSeesion = MybatisUtils.getSqlSeesion(); UserMapper mapper = sqlSeesion.getMapper(UserMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("userId",null); map.put("userNamae","zhangsan"); map.put("userPassword","123456"); int i = mapper.addUser2(map); sqlSeesion.commit(); sqlSeesion.close(); }
map傳遞引數,直接在SQL中取出key即可!【parameterType="map"】
物件傳遞引數,直接在sql中取物件的屬性即可!【parameterType="Object"】
只有一個基本型別引數的情況下,可以直接在SQL中取到。
多個引數用map,或註解
8、模糊查詢
-
java程式碼執行的時候,傳遞萬用字元
List<User> a = mapper.getUserLike("%a%");
-
在sql拼接中使用萬用字元
select * from user where name like "%"#{value}"%"
-
4、配置解析
1、核心配置檔案
-
mybatis-config.xm
-
Mybatis的配置檔案包含了會深深影響Mybatis行為的設定和屬性資訊。
configuration(配置) properties(屬性) settings(設定) typeAliases(類型別名) typeHandlers( ) objectFactory(物件工廠) plugins(外掛) environments(環境配置) environment(環境變數) transactionManager(事務管理器) dataSource(資料來源) databaseIdProvider(資料庫廠商標識) mappers(對映器)
2、環境配置(environments)
MyBatis 可以配置成適應多種環境,
不過要記住:儘管可以配置多個環境,但每個 SqlSessionFactory 例項只能選擇一種環境。
學會使用配置多套執行環境
mybatis的預設事務管理器就是JDBC,連線池:POOLED
3、屬性(properties)
我們可以通過properties屬性來實現引用配置檔案
這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定。例如: 這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定。例如:【druid.properties】
編寫一個配置檔案
druid.properties
#key=value driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=UTF-8 #url=jdbc:mysql://localhost:3306/itheima username=root password=root #initial connection Size initialSize=10 #min idle connecton size minIdle=5 #max active connection size maxActive=20 #max wait time (5000 mil seconds) 最大等待時間 maxWait=5000
在核心配置檔案中引入
<properties resource="druid.properties"/> <environments default="development">
-
可以直接引入外部檔案
-
可以在其中增加一些屬性配置
-
如果兩個檔案有同一個欄位,優先使用外部配置檔案的!
-
4、類型別名(typeAliases)
-
類型別名可為 Java 型別設定一個縮寫名字。
-
它僅用於 XML 配置,意在降低冗餘的全限定類名書寫
<!--可以給實體類起別名--> <typeAliases> <typeAlias type="com.qiang.pojo.User" alias="User"/> </typeAliases>
也可以指定一個包名,MyBatis 會在包名下面搜尋需要的 Java Bean 比如:
掃描實體類的包,他預設別名就為這個類的類名,首字母小寫
<typeAliases>
<package name="com.qiang.pojo"/>
</typeAliases>
在實體類比較少的情況下,建議使用第一種方式
如果實體類非常多,建議使用第二種。
第一種可以DIY,第二種則不行(相對來說,可以在實體類上加註解起)
優先順序:類型別名>註解別名>包別名
5、設定(settings)
這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的執行時行為
設定名 | 描述 | 有效值 | 預設值 |
---|---|---|---|
cacheEnabled | 全域性性地開啟或關閉所有對映器配置檔案中已配置的任何快取。 | true | false | true |
lazyLoadingEnabled | 延遲載入的全域性開關。當開啟時,所有關聯物件都會延遲載入。 特定關聯關係中可通過設定 fetchType 屬性來覆蓋該項的開關狀態。 |
true | false | false |
logImpl | 指定 MyBatis 所用日誌的具體實現,未指定時將自動查詢。 | SLF4J | LOG4J(deprecated since 3.5.9) |
6、其他配置
-
-
mybatis Plus
-
通用mapper
7、對映器(mappers)
MapperRegistry:註冊繫結我們得Mapper檔案
方式一:
<!--每一個Mapper.xml都需要在Mybatis核心配置檔案中註冊!--> <mappers> <mapper resource="com/qiang/dao/UserMapper.xml"/> </mappers>
方式二:使用class檔案註冊繫結
<!--每一個Mapper.xml都需要在Mybatis核心配置檔案中註冊!--> <mappers> <mapper class="com/qiang/dao/UserMapper"/> </mappers>
注意點:
-
介面必須和他的Mapper檔案必須同名
-
介面必須和他的Mapper檔案必須在同一個包下!
方式三:使用掃描包進行註冊繫結
<!--每一個Mapper.xml都需要在Mybatis核心配置檔案中註冊!--> <mappers> <package class="com/qiang/dao"/> </mappers>
注意點:
-
介面必須和他的Mapper檔案必須同名
-
介面必須和他的Mapper檔案必須在同一個包下!
8、生命週期
生命週期、類別是至關重要的,因為錯誤的使用會導致非常嚴重的併發問題。
SqlSessionFactoryBuilder
-
一旦建立了SqlSessionFactory就不需要它了
-
區域性變數
SqlSessionFactory
-
說白了就可以想象成:資料庫連線池
-
SqlSessionFactory 一旦被建立就應該在應用的執行期間一直存在 , 沒有任何理由丟棄它或重新建立另一個例項
-
因此 SqlSessionFactory 的最佳作用域是應用作用域
-
最簡單的就是使用單例模式或者靜態單例模式。
SqlSession
-
連線到連線池的一個請求!
-
SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
-
用完之後需要趕緊關閉,否則資源被佔用!
這裡的每一個mapper程式碼,就代表一個具體的業務!
5、解決屬性名和欄位名不一致的問題
1、問題
資料庫中的欄位與實體對應pojo欄位不一樣
解決方式一:起別名
<select id="getUserList" resultType="user"> select id,name,pwd as password from mybatis.user </select>
2、resultMap
結果集對映
id name pwd id name password
<!--結果集對映--> <resultMap id="UserMap" type="User"> <!-- column:資料庫對映欄位 property:實體類屬性 --> <result column="pwd" property="password"/> </resultMap>
-
resultMap元素是MyBatis中最強大的元素
-
ResultMap的設計思想是,對於簡單的語句根本不需要配置顯式
的結果集對映,而對於複雜一點的語句只需要描述他們的關係就行了
6、日誌
1、面象介面程式設計
- 大家之前都學過面向物件程式設計,也學習過介面,但在真正的開發中,很多時候我們會選擇面向介面程式設計 - 根本原因:解耦,可拓展,提高複用,分層開發中,上層不用管具體的實現,大家都遵守共同的標準,使得開發變得更容易,規範性更好 - 在一個面向物件的系統中,系統的各種功能是由許許多多的不同物件協作完成的。在這種情況下,各個物件內部是如何實現自己的,對系統設計人員來講就不那麼重要了; - 而各個物件之前的協作關係則成為系統設計的關鍵,小到不同類之間的通訊,大到各模組之間的互動,在系統設計之初都是要著重考慮的,這也是系統設計的主要工作內容,面向介面程式設計就是指按照這種思想來程式設計。關於介面的理解
- 介面從更深層次的理解,應是定義(規範,約束)與實現(名實分離)的分離。
- 介面的本身反映了系統設計人員對系統的抽象理解。
- 介面應有兩類:
- 第一類是對一個個體的抽象,它可對應為一個抽象體(abstract class); - 第二類是對一個個體某一方面的抽象,即形成一個抽象面(interface);
- 一個體有可能有多個抽象面,抽象體與抽象面是有區別的
三個面向區別
- 面向物件是指,我們考慮問題時,以物件為單位,考慮它的屬性及方法 - 面向過程是指,我們考慮問題時,以一個具體的流程(事務過程)為單位,考慮它的實現。 - 介面設計與非介面設計是針對複用技術而言的,與面向物件(過程)不是一個問題,更多的體現就是對系統整體的架構
6.1、日誌工廠
如果一個數據庫操作,出現了異常,我們需要拍錯。日誌就是最好的助手!
曾經:sout、debug
現在日誌工廠
-
SLF4J
-
LOG4J(deprecated since 3.5.9) 【掌握】
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING 【掌握】
-
NO_LOGGING
在Mybatis中具體使用使用哪一個日誌實現,在設定中設定
STDOUT_LOGGING 標準日誌輸出
<settings>
<!-- 標準的日誌工廠實現-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
Class not found: org.jboss.vfs.VFS
JBoss 6 VFS API is not available in this environment.
Class not found: org.jboss.vfs.VirtualFile
VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
Using VFS adapter org.apache.ibatis.io.DefaultVFS
Find JAR URL: file:/F:/code/mybatis/mybatis-03/target/classes/com/qiang/pojo
Not a JAR: file:/F:/code/mybatis/mybatis-03/target/classes/com/qiang/pojo
Reader entry: User.class
Listing file:/F:/code/mybatis/mybatis-03/target/classes/com/qiang/pojo
Find JAR URL: file:/F:/code/mybatis/mybatis-03/target/classes/com/qiang/pojo/User.class
Not a JAR: file:/F:/code/mybatis/mybatis-03/target/classes/com/qiang/pojo/User.class
Reader entry: ���� 1 <
Checking to see if class com.qiang.pojo.User matches criteria [is assignable to Object]
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.