一、Mybatis 簡介
1、什麼是MyBatis?
官網位址
- MyBatis 是一款優秀的持久層架構,
- 它支援定制化 SQL、存儲過程以及進階映射。
- MyBatis 避免了幾乎所有的 JDBC 代碼和手動設定參數以及擷取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生資訊。
Maven倉庫獲得Mybatis:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
2、資料的持久化
資料的持久化就是把程式中的資料從瞬時狀态轉化為持久狀态的過程。
二、編寫第一個MyBatis程式
搭建環境
資料庫環境:
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'李磊','123456'),
(2,'趙巷','123456'),
(3,'王靜怡','11235813')
Maven導入依賴:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
編寫配置檔案: mybatis-config.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>
<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&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="11235813"/>
</dataSource>
</environment>
</environments>
</configuration>
編寫資料庫工具類
package com.zyh.utils;
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 java.io.IOException;
import java.io.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "mybatis-config.xml";
{
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
//工廠模式
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//擷取連接配接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
編寫一個實體類:使用lombok注解
package com.zyh.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
編寫持久層的操作接口:
package com.zyh.mapping;
import com.zyh.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> getUserList();
}
編寫持久層接口的配置檔案
<?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的作用:和你編寫的持久層的接口關聯起來-->
<mapper namespace="com.zyh.mapping.UserMapper">
<select id="selectBlog" resultType="Blog">
select * from `user`;
</select>
</mapper>
将你編寫的配置檔案注冊到 mybatis-config.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>
<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?useUnicode=true&characterEncoding=utf8&useSSL=true"/>
<property name="username" value="root"/>
<property name="password" value="11235813"/>
</dataSource>
</environment>
</environments>
<!--寫好的接口配置檔案注冊到mybatis-config.xml 配置檔案中-->
<mappers>
<mapper resource="com/zyh/mapping/UserMapper.xml"/>
</mappers>
</configuration>
測試:
import com.zyh.mapping.UserMapper;
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class Test {
public static void main(String[] args) {
// 1、擷取SqlSession連接配接,用于執行sql
SqlSession sqlSession = MyBatisUtils.getSession();
//2、通過session.getMapper(class) 擷取接口
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
}
執行結果:
三、生命周期和作用域
圖示:
1、SqlSessionFactoryBuilder類
SqlSessionFactory 的建立,需要使用SqlSessionFactoryBuilder對象的build()方法。由于SqlSessionFactoryBuilder 對象在建立完工廠對象後,就完成了其曆史使命,即可被銷毀。是以,一般會将該 SqlSessionFactoryBuilder 對象建立為一個方法内的局部對象,方法結束,對象銷毀。
2、SqlSessionFactory接口
SqlSessionFactory 接口對象是一個重量級對象(系統開銷大的對象),是線程安全的,是以一個應用隻需要一個該對象即可。建立SqlSession需要使用SqlSessionFactory接口的的openSession()方法。
- 可以被了解為資料庫的連接配接池。
- SqlSessionFactary 一旦被建立,就應該在應用的運作期間一直存在,不應該丢棄或建立一個新的執行個體。
3、 SqlSession接口
- SqlSession 接口對象用于執行持久化操作。一個 SqlSession 對應着一次資料庫會話,一次會話以 SqlSession 對象的建立開始,以SqlSession對象的關閉結束。
- SqlSession 接口對象是線程不安全的,是以每次資料庫會話結束前,需要馬上調用其 close() 方法,将其關閉。 再次需要會話,再次建立。而在關閉時會判斷目前的SqlSession是否被送出:若沒有被送出,則會執行復原後關閉;若已被送出,則直接将 SqlSession 關閉。是以,SqlSession 無需手工復原。
四、CRUD操作
1、select 查詢
編寫接口代碼:
public interface UserMapper {
//根據使用者的id查詢使用者
User getUserById(int id);
}
編寫配置檔案
<mapper namespace="com.zyh.mapping.UserMapper">
<select id="getUserById" parameterType="int" resultType="com.zyh.pojo.User">
select * from mybatis.user where id = #{id};
</select>
</mapper>
測試:
public class Test {
public static void main(String[] args) {
SqlSession session = MyBatisUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);
session.close();
}
執行結果:
2、insert 插入資料
編寫接口:
//添加一個使用者
int addUser(User user);
編寫配置檔案:
<insert id="addUser" parameterType="com.zyh.pojo.User">
insert into `user`(`id`,`name`,`pwd`) values (#{id},#{name},#{pwd});
</insert>
測試:
public class Test {
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/* 增删改必須開啟事務 */
int i = mapper.addUser(new User(4,"張成西","11235813"));
sqlSession.commit();
if (i > 0) {
System.out.println("添加使用者成功");
}
}
}
3、update 修改資料庫資料
編寫接口:
//修改使用者資訊
int updateUser(User user);
編寫配置檔案:
<update id="updateUser" parameterType="com.zyh.pojo.User">
update `user` set `name` = #{name}, pwd = #{pwd} where id = #{id};
</update>
測試:
public class Test {
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/* 增删改必須開啟事務 */
int i = mapper.updateUser(new User(4, "haha", "123456"));
sqlSession.commit();
if (i > 0) {
System.out.println("修改成功!");
}
}
}
4、delete 删除資料
編寫接口:
//删除使用者
int deleteUserById(int id);
編寫配置檔案:
<delete id="deleteUserById" parameterType="int">
delete from `user` where `id` = #{id};
</delete>
測試:
public class Test {
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/* 增删改必須開啟事務 */
int i = mapper.deleteUserById(4);
sqlSession.commit();
if (i > 0) {
System.out.println("删除成功!");
}
}
}
五、配置檔案解析
mybatis-config.xml 檔案
configuration(配置)
properties(屬性)
settings(設定)
typeAliases(類型别名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境配置)
environment(環境變量)
transactionManager(事務管理器)
dataSource(資料源)
databaseIdProvider(資料庫廠商辨別)
mappers(映射器)<!--綁定mapper配置檔案-->
properties 用來引用本地配置檔案
編寫一個db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=true&characterEnicoding=utf8
username=root
pwd=123456
在配置檔案中引用:
<?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>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!--寫好的接口配置檔案注冊到mybatis-config.xml 配置檔案中-->
<mappers>
<package name="com.zyh.mapping"></package>
</mappers>
</configuration>
在mybatis-config.xml中給包配置别名:
<properties resource="db.properties"></properties>
<typeAliases>
<!--這個包下的所有實體類都會被自動掃描到-->
<!--<package name="com.zyh.pojo"></package>-->
<!--給這個包下的User類起一個别名 User,每次隻能改一個-->
<typeAlias type="com.zyh.pojo.User" alias="User"></typeAlias>
</typeAliases>
配置 settings,開啟日志
<properties resource="db.properties"></properties>
<!--settings大小寫不要寫錯-->
<settings>
<!--配置日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
六、解決資料庫字段名和實體類屬性名不一緻問題(ResultMap)
如果實體類屬性和資料庫中的字段值一緻,Mybatis 就會自動推斷并映射,這叫做自動映射。
如果不一緻們就需要我們進行手動映射。
資料庫中的字段名:
實體類中的字段名:
password 字段屬性值和資料庫不一緻。我們編寫好測試代碼後查詢使用者資訊發現:
發現 password 為 null。
解決方案:
- 給SQL語句查詢時為 password 起一個别名
select id,name,pwd as password from user where id = #{id};
-
結果集映射
編寫接口:
package com.zyh.mapping;
import com.zyh.pojo.User;
public interface RsMapper {
User selectUserById(int id);
}
編寫接口配置檔案:
<?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的作用:和你編寫的持久層的接口關聯起來-->
<mapper namespace="com.zyh.mapping.RsMapper">
<!--結果集映射resultMap -->
<resultMap id="UserMap" type="User">
<!--主鍵一般使用id标簽-->
<id column="id" property="id"/>
<!--column 對應資料庫中的字段名 property對應實體類中的屬性名-->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="selectUserById" resultMap="UserMap">
select * from `user` where `id`= #{id};
</select>
</mapper>
測試類:
import com.zyh.mapping.RsMapper;
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
public class Test2 {
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
RsMapper mapper = sqlSession.getMapper(RsMapper.class);
User user = mapper.selectUserById(3);
System.out.println(user);
}
}
執行結果:
這次資料庫中的
pwd
字段的值就被讀取出來了。
七、日志和分頁
1、日志
日志的作用: 在我們的工作中,如果出現了錯誤,日志就可以幫助我們排除錯誤。
MyBatis 的預設日志:
<settings>
<!--配置日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
但目前使用最多的就是 Apache 的 Log4j 日志。
使用Log4j
步驟:
- 導入包依賴:去 Maven 倉庫 下載下傳。
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- 在MyBatis 核心配置檔案中,設定為LOG4J日志
<settings>
<!--配置日志 LOG4J 要求為大寫-->
<setting name="logImpl" value="LOG4J"/>
</settings>
- 測試:列印輸出的時候就會後日志檔案。
使用Log4J輸出資訊:
import com.zyh.mapping.RsMapper;
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
public class Test2 {
static Logger logger = Logger.getLogger(Test2.class);
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
RsMapper mapper = sqlSession.getMapper(RsMapper.class);
User user = mapper.selectUserById(3);
System.out.println(user);
//Log4j 将日志設定為較為詳細的輸出
logger.error("111111111111"); //輸出的錯誤資訊
logger.debug("2222222222222"); //debug 資訊
logger.info("333333333333333"); //輸出的提示資訊
}
}
2、分頁
limit 分頁:SQL層面實作分頁
分頁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的作用:和你編寫的持久層的接口關聯起來-->
<mapper namespace="com.zyh.mapping.RsMapper">
<!--結果集映射resultMap -->
<resultMap id="UserMap" type="User">
<!--主鍵一般使用id标簽-->
<id column="id" property="id"/>
<!--column 對應資料庫中的字段名 property對應實體類中的屬性名-->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
select * from `user` limit #{startIndex}, #{pageSize};
</select>
</mapper>
測試:
import com.zyh.mapping.RsMapper;
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import java.util.HashMap;
import java.util.List;
public class Test2 {
static Logger logger = Logger.getLogger(Test2.class);
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtils.getSession();
RsMapper mapper = sqlSession.getMapper(RsMapper.class);
int currentPage = 1; //目前頁面
int pageSize = 2; //每頁顯示幾個
HashMap<String,Integer> map = new HashMap<String, Integer>();
map.put("startIndex",(currentPage-1) * pageSize);
map.put("pageSize",pageSize);
List<User> users = mapper.getUserByLimit(map);
mapper.getUserByLimit(map);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
執行結果:
RowBounds 分頁 Java 層面實作
接口:
/**
* RowBounds 分頁
*/
List<User> getUserByRowBounds();
接口配置檔案:
<select id="getUserByRowBounds" parameterType="map" resultMap="UserMap">
select * from `user`;
</select>
測試:
import com.zyh.pojo.User;
import com.zyh.utils.MyBatisUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class Test3 {
public static void main(String[] args) {
SqlSession session = MyBatisUtils.getSession();
//RowBounds分頁,從第一個使用者開始,每頁兩個使用者資料
RowBounds rowBounds = new RowBounds(0,2);
//Java代碼實作分頁
List<User> userList = session.selectList("com.zyh.mapping.RsMapper.getUserByRowBounds",null,rowBounds);
for (User user : userList) {
System.out.println(user);
}
session.close();
}
}
執行結果: