[JS設計模式]:鴨子型別與多型
Mybatis
環境
- JDk1.8
- Mysql 5.7
- maven 3.6.1
- IDEA
回顧
- JDBC
- Mysql
- java基礎
- Maven
- Junit
SSM框架
配置檔案,看官網文件
1、簡介
1.1 什麼是Mybatis
-
MyBatis 是一款優秀的持久層框架,
-
它支援自定義 SQL、儲存過程以及高階對映。
-
MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來配置和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。
1.2 如何獲得Mybatis
-
maven倉庫:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency>
-
Github: https://github.com/mybatis/mybatis-3/releases
持久層
資料持久化
- 持久化就是將程式在持久狀態和瞬時狀態轉化的過程
目的:幫助程式設計師將資料存到資料庫中
2、第一個Mybatis程式
思路:搭建環境-->匯入Mybatis-->編寫程式碼-->測試!
2.1 搭建環境
新建專案
- 新建一個普通Maven專案
- 刪除src目錄
- 匯入Maven依賴
<dependencies> <!--mysql驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <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> </dependency> </dependencies>
2.2 建立一個模組
- 編寫mybatis的核心配置檔案
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置檔案-->
<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=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="wrz485251mysql"/>
</dataSource>
</environment>
</environments>
</configuration>
- 編寫mybatis工具類
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
// 使用Mybatis第一步:獲取sqlSessionFactory物件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
2.3、編寫程式碼
- 實體類
public class User {
private int id;
private String userName;
private int userPassword;
private int phone;
public User() {
}
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 int getUserPassword() {
return userPassword;
}
public void setUserPassword(int userPassword) {
this.userPassword = userPassword;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
public User(int id, String userName, int userPassword, int phone){
this.id=id;
this.userName=userName;
this.userPassword=userPassword;
this.phone= phone;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", userPassword=" + userPassword +
", phone=" + phone +
'}';
}
}
- Dao介面
public interface UserDao {
List<User> getUserList();
}
- 介面實現類由原來的UserDaoImpl轉變為一個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=繫結一個對應的Dao/Mapper介面-->
<mapper namespace="com.guo.dao.UserDao">
<select id="getUserList" resultType="com.guo.pojo.User" >
select * from smbms.smbms_user
</select>
</mapper>
2.4、測試
- junit 測試
@Test
public void test(){
// 第一步:獲得SqlSession物件
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for(User user:userList){
System.out.println(user);
}
// 關閉SqlSession
sqlSession.close();
}
3、CEUD
3.1 namespace
namespace種的包名要和Dao/mapper介面的包名一致!
3.2 select
選擇,查詢語句:
- id: 就是對應的namespace中的方法名;
- resultType: Sql語句執行的返回值!
- parameterType: 引數型別!
- 編寫介面
User getUserById(int id);
- 編寫對應的mapper中的sql語句
<select id="getUserById" resultType="com.guo.pojo.User" parameterType="int" >
select * from smbms.smbms_user where id = #{id}
</select>
- 測試
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
3.3 insert
<insert id="addUser" parameterType="com.guo.pojo.User">
insert into smbms.smbms_user (id,userName,userPassword) values (#{id},#{userName},#{userPassword});
</insert>
*** 注意點:增刪改需要提交事務! ***
3.4 萬能Map
假如實體類或者資料庫的表,欄位或者引數過多,應該考慮使用Map!
int addUser2(Map<String,Object> map);
<!-- 物件中的屬性,可以直接取出來傳遞map的key -->
<insert id="addUser" parameterType="map">
insert into smbms.smbms_user (id,userName,userPassword) values (#{userid },#{userName},#{userPassword});
</insert>
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<>();
map.put("userid",5);
map.put("userName","Hello");
map.put("userPassword","2333344");
mapper.addUser2(map);
sqlSession.close();
}
3.5 模糊查詢怎麼寫
- java程式碼執行的時候,傳遞萬用字元%%
List<User> userList = mapper.getUserLike("%李%");
-
在sql拼接中使用萬用字元!
select * from mybatis.user where name like "%"#{value}"%"
4、 配置解析
4.1 核心配置檔案
-
mybatis-config,xml
-
MyBatis 的配置檔案包含了會深深影響 MyBatis 行為的設定和屬性資訊。 配置文件的頂層結構如下:
configuration(配置) properties(屬性) settings(設定) typeAliases(類型別名) typeHandlers(型別處理器) objectFactory(物件工廠) plugins(外掛) environments(環境配置) environment(環境變數) transactionManager(事務管理器) dataSource(資料來源) databaseIdProvider(資料庫廠商標識) mappers(對映器)
4.2 環境配置
- myBatis可以配置成適應多種環境
- 儘管可以配置多種環境。但每個SqlSessionFactory例項只能選擇一種環境
- 學會使用配置多套執行環境
- myBatis預設的事務管理器就是JDBC,連線池:POOLED
4.3 屬性
-
這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定
-
編寫一個配置檔案
db.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=false;useUnicode=true;characterEncoding=UTF-8 username=root password=wrz485251mysql
在核心配置檔案中引入
<!-- 引入外部配置檔案 --> <properties resource="db.properties"/>
-
可以直接引入外部檔案
-
可以在其中增加一些配置屬性
-
如果兩個檔案有同一欄位,優先使用外部配置檔案!
4.4 類型別名
- 類型別名是為Java型別設定一個短的名字
- 存在的意義僅用來減少完全限定名的冗餘
<!-- 別名 -->
<typeAliases>
<typeAlias type="com.guo.pojo.User" alias="User"/>
</typeAliases>
-
也可以指定一個包名,MyBatis會在包名下搜尋需要的javaBean,比如:掃描實體類的包,預設為這個類的類名,首字母小寫!
<!-- 別名 --> <typeAliases> <package name="com.guo.pojo"/> </typeAliases>
4.5 對映器
MapperRegisty: 註冊繫結我們的Mapper檔案
-
方式一:
!-- 每一個Mapper.XML都需要在Mybatis核心配置檔案中註冊 --> <mappers> <mapper resource="com/guo/dao/UserMapper.xml"/> </mappers>
-
方式二:使用class檔案繫結註冊
<mappers> <!-- <mapper resource="com/guo/dao/UserMapper.xml"/>--> <mapper class="com.guo.dao.UserMapper"/> </mappers>
注意點:
- 介面和配置檔案必須同名!
- 介面和配置檔案必須在同一個包下!
-
方式三:使用掃描包進行注入繫結
<mappers> <!--<mapper resource="com/guo/dao/UserMapper.xml"/>--> <package name="com.guo.dao"/> </mappers>
4.6 生命週期和作用域
理解我們之前討論過的不同作用域和生命週期類別是至關重要的,因為錯誤的使用會導致非常嚴重的併發問題。
生命週期
SqlSessionFactoryBuilder:
- 一旦建立了 SqlSessionFactory,就不再需要它了
- 區域性變數
SqlSessionFactory:
- 可以想象為資料庫連線池
- SqlSessionFactory 一旦被建立就應該在應用的執行期間一直存在,沒有任何理由丟棄它或重新建立另一個例項。
- 最簡單的就是使用單例模式或者靜態單例模式。
SqlSession:
- 連線到連線池的一個請求!
- SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
- 用完之後趕緊關閉,否則資源被佔用
這裡面的每一個Mapper,就代表一個具體的業務!
5、解決屬性名和欄位名不一致的問題
5.1 結果集對映
resultMap
元素是 MyBatis 中最重要最強大的元素- ResultMap 的設計思想是,對簡單的語句做到零配置,對於複雜一點的語句,只需要描述語句之間的關係就行了。
6、日誌
6.1 日誌工廠
在Mybatis中具體使用哪一個日誌實現,在設定中設定!
STDOUT_LOGGING標準日誌輸出
在mybatis核心配置檔案中,配置我們的日誌!
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
6.2、Log4j
6.2.1 什麼是Log4j
- Log4j是Apache的一個開源專案,通過使用Log4j,我們可以控制日誌資訊輸送的目的地是控制檯、檔案、GUI元件
- 我們也可以控制每一條日誌的輸出格式
- 通過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程
- 通過一個配置檔案來靈活地進行配置,而不需要修改應用的程式碼。
6.2.2 設定相關依賴
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
6.2.3 log4j.properties
#將等級為DEBUG的日誌資訊輸出到console和file這兩個目的地,console和file的定義在下面的程式碼
log4j.rootLogger=DEBUG,console,file
#控制檯輸出的相關設定
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n
#檔案輸出的相關設定
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n
#日誌輸出級別
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
6.2.4 配置log4j為日誌的實現
<settings>
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<setting name="logImpl" value="LOG4J"/>
</settings>
6.2.5 Log4j的使用
6.2.5 簡單使用
-
匯入相關包
-
日誌物件,引數為當前類的class
static Logger logger = Logger.getLogger(UserMapper.class);
-
日誌級別
7、分頁
目的:減少資料的處理量
7.1 使用Limit分頁
語法:SELECT * from user limit startIndex,pageSize;
SELECT * from user limit 3; #[0,n]
使用Mybatis實現分頁,核心SQL
-
介面
//分頁 List<User> getUserByLimit(Map<String,Integer> map);
-
Mapper,XML
<!-- 分頁 --> <select id="getUserByLimit" parameterType="map" resultType="user"> select * from smbms.smbms_user limit #{startIndex},#{pageSize} </select>
-
測試
@Test public void getUserByLimit(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); HashMap<String, Integer> map = new HashMap<>(); map.put("startIndex",1); map.put("pageSize",2); List<User> userList = mapper.getUserByLimit(map); for(User user:userList){ System.out.println(user); } sqlSession.close(); }
8、使用註解
8.1 使用註解開發
-
註解在介面實現
@Select("select * from user") List<User> getUsers();
-
需要在核心配置檔案中繫結介面!
<!-- 繫結介面 --> <mappers> <mapper class="com.guo.dao.UserMapper"/> </mappers>
本質:反射機制實現
底層:動態代理!
8.2 CRUD
我們可以在工具類建立的時候實現自動提交事務!
編寫介面,增加註釋
-
測試類:注意我們必須要將介面註冊繫結到我們的核心配置檔案中!
關於@Param()註解
- 基本型別的引數或者String型別,需要加上
- 引用型別不需要加
- 在Sql中引用的就是在@Param中設定的屬性名!
9、Lombok(等研三找工作時在用)
- 在IDEA中安裝Lombok外掛
- 在專案中匯入相關jar包
@Data: 無參構造,get, set, tostring, hashcode, equals
10、多對一處理
多對一:
- 多個學生,對應一個老師
- 對於學生而言,多個學生關聯一個老師【多對一】
- 對於老師而言,集合,一個老師,有很多學生【一對多】
10.1 測試環境搭建
- 匯入lombok
- 新建實體類Teacher,Student
- 建立Mapper介面
- 建立Mapper.xml檔案
- 在核心配置檔案中繫結註冊我們的Mapper介面或者檔案!
- 測試查詢是否成功!
10.2 按照查詢巢狀處理
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.guo.dao.StudentMapper">
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="com.guo.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!-- 複雜的屬性,我們需要單獨處理
物件:association
集合:collection
-->
<association property="teacher" column="tid" javaType="com.guo.pojo.Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="com.guo.pojo.Teacher">
select * from teacher where id = #{id}
</select>
</mapper>
10.3 按照結果巢狀處理
<!-- 按照結果巢狀查詢處理 -->
<select id="getStudent2" resultMap="StudentTeacher2">
select student.id sid,student.name sname,teacher.name tname
from student,teacher
where student.id = teacher.id;
</select>
<resultMap id="StudentTeacher2" type="com.guo.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="com.guo.pojo.Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
注意:對映檔案中實體類名要寫全限定名
回顧Mysql多對一查詢方式:
- 子查詢
- 聯表查詢
11、動態SQL
11.1 IF
<select id="queryBlogIF" parameterType="map" resultType="com.guo.pojo.Blog">
select * from mybatis.blog where 1=1
<if test=" title != null">
and title = #{title}
</if>
<if test="author!= null">
and author = #{author}
</if>
</select>
11.2 choose(when,otherwise)
<select id="queryBlogChoose" parameterType="map" resultType="com.guo.pojo.Blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
所謂的動態SQL,本質還是SQL語句,只是我們可以在SQL層面,去執行一個邏輯程式碼
12、快取
12.1 簡介
- 存放在記憶體的臨時資料