Mybatis介紹
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。
2013年11月遷移到Github。MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。Mybatis通過xml或注解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最后由mybatis框架執行sql並將結果映射成java對象並返回。
Mybatis框架
框架介紹
1、 mybatis配置
SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。
2、 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
3、 由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行。
4、 mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
5、 Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。
6、 Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
7、 Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。
利用IDEA創建Mybatis的入門案例
8個步驟
- 創建maven工程,什么都不選就ok,並導入坐標;
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
- 編寫User實體類
public class User implements Serializable {
private int id;
private String username;// 用戶姓名
private String sex;// 性別
private Date birthday;// 生日
private String address;// 地址
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex
+ ", birthday=" + birthday + ", address=" + address + "]";
}
}
-
在resources文件夾中,創建Mybatis的主配置文件SqlMapConfig.xml。它是mybatis核
心配置文件,配置文件內容為數據源、事務管理。
配置環境:
- 配置mysql的環境:
- 配置事務的類型;
- 配置連接池:配置連接數據庫的4個基本信息;
- 指定映射配置文件的位置:
代碼如下:
<?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="mysql">
<!--配置mysql的環境-->
<environment id="mysql">
<!--配置事務的類型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置連接池-->
<dataSource type="POOLED">
<!--配置連接數據庫的4個基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.214.128:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="ben123"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件指的是每個dao獨立的配置文件-->
<mappers>
<mapper resource="com/ben/dao/IUserDao.xml"/>
</mappers>
</configuration>
- 在resources文件夾中導入log4j.properties文件
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
- 編寫映射文件 IUserDao.xml ,位置在目錄resource->sqlmap->User.xml
<?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="test">
</mapper>
- 加載映射文件,將User.xml添加在SqlMapConfig.xml下
<!--指定映射配置文件的位置-->
<mappers>
<mapper resource="sqlmao/User.xml"/>
</mappers>
- 編寫測試類:在test->java目錄下創建測試類com.ben.test.MybatisTest。實現業務需求,共7步,其中2,3步可以合在一起。
1. 加載核心配置文件SqlMapConfig.xml
2. 創建SqlSessionFactoryBuilder對象
3. 創建SqlSessionFactory對象(2,3可以寫一起)
4. 創建SqlSession對象
5. 執行SqlSession對象執行查詢,獲取結果User
6. 打印結果
7. 釋放資源
代碼如下:
package com.ben.test;
import com.ben.domain.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;
import java.util.Date;
import java.util.List;
/**
* @ClassName: MybatisTest
* @author: benjamin
* @version: 1.0
* @description: TODO
* @createTime: 2019/07/13/11:50
*/
public class MybatisTest {
public static void main(String[] args) {
}
//通過Id查詢一個用戶
@Test
public void testSearchById() throws IOException {
//1.讀取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3.使用工廠生產SqlSession對象
SqlSession session = sqlSessionFactory.openSession();
//4.執行Sql語句
User user = session.selectOne("test.findUserById", 10);
//5. 打印結果
System.out.println(user);
//6.釋放資源
session.close();
in.close();
}
//根據用戶名模糊查詢用戶列表
@Test
public void testFindUserByUsername() throws IOException {
//1.讀取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3.使用工廠生產SqlSession對象
SqlSession session = sqlSessionFactory.openSession();
//4.執行Sql語句
List<User> list = session.selectList("test.findUserByUsername", "王");
//5. 打印結果
for (User user:list) {
System.out.println(user);
}
//6.釋放資源
session.close();
in.close();
}
//添加用戶
@Test
public void testInsertUser() throws IOException {
//1.讀取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3.使用工廠生產SqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.執行Sql語句
User user = new User();
user.setUsername("小強");
user.setBirthday(new Date());
user.setAddress("sadfsafsafs");
user.setSex("2");
int i = sqlSession.insert("test.insertUser", user);
sqlSession.commit();
//5. 打印結果
// 剛保存用戶,此時用戶ID需要返回。執行完上面insert程序后,此時就能知道用戶的ID是多少
// 需要在User.xml文件中配置
System.out.println("插入id:"+user.getId());//插入id:30
//6.釋放資源
sqlSession.close();
in.close();
}
//更新用戶
@Test
public void testUpdateUserById() throws IOException {
//1.讀取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3.使用工廠生產SqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.執行Sql語句
User user = new User();
user.setId(27);
user.setUsername("小小");
user.setBirthday(new Date());
user.setAddress("西安市");
user.setSex("1");
int i = sqlSession.insert("test.updateUserById", user);
sqlSession.commit();
//5. 打印結果
System.out.println(user.getId());
//6.釋放資源
sqlSession.close();
in.close();
}
//刪除用戶
@Test
public void testDeleteUserById() throws IOException {
//1.讀取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//3.使用工廠生產SqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.執行Sql語句
int i = sqlSession.insert("test.deleteUserById", 32);
sqlSession.commit();
//5. 打印結果
System.out.println(i);
//6.釋放資源
sqlSession.close();
in.close();
}
}
- 配置映射配置文件User.xml
<?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="test">
<!-- 通過Id查詢一個用戶 -->
<select id="findUserById" parameterType="Integer" resultType="com.ben.domain.User">
select * from user where id = #{v}
</select>
<!-- 根據用戶名模糊查詢用戶列表 -->
<!-- select * from user where username like '%${value}%'-->
<!-- select * from user where username like "%"#{value}"%"-->
<select id="findUserByUsername" parameterType="String" resultType="com.ben.domain.User">
select * from user where username like #{username}
</select>
<!-- 添加用戶 -->
<insert id="insertUser" parameterType="com.ben.domain.User">
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,address,sex) values(#{username},#{birthday},#{address},#{sex})
</insert>
<!-- 更新用戶 -->
<update id="updateUserById" parameterType="com.ben.domain.User">
update user
set username = #{username},sex = #{sex},birthday = #{birthday},address = #{address}
where id = #{id}
</update>
<!-- 刪除用戶 -->
<delete id="deleteUserById" parameterType="Integer">
delete from user
where id = #{vvvvv}
</delete>
</mapper>
注意事項
詳解參數
namespace:用來區別不同的類的名字
id:標識映射文件中的sql,稱為statement的id將sql語句封裝到mappedStatement對象中,所以將id稱為statement的id
parameterType:指定輸入參數的類型.
resultType:指定輸出結果類型。mybatis將sql查詢結果的一行記錄數據映射為resultType指定類型的對象。如果有多條數據,則分別進行映射,並把對象放到容器List中
#{}:一個占位符。preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換。#{}可以有效防止sql注入。 #{}可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。
${}:表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換,${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value。
解釋select語句
這一部分參考mybatis官網。詳情點擊http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
<select id="findUserById" parameterType="Integer" resultType="com.ben.domain.User">
select * from user where id = #{v}
</select>
這個語句被稱作findUserById, 接受一個Integer類型的參數,返回一個User對象。#{V} 告訴mybatis創建一個預處理語句參數,在JDBC中,這個的一個參數在Sql中會由一個“ ?”表示,並被傳遞到新的預處理語句中,如:
//近似的JDBC代碼,並非Mybatis代碼
String findUserById = "select * from user where id = ?";
PreparedStatement ps = conn.prepareStatement(findUserById);
ps.setInt(1,id);
使用 JDBC 意味着需要更多的代碼來提取結果並將它們映射到對象實例中,而這就是 MyBatis 節省你時間的地方.
注意
- 在根據用戶名模糊查詢中注意:有兩種寫法。
1.測試類中這樣寫:
List<User> list = session.selectList("test.findUserByUsername", "王");
在User.xml中寫:
select * from user where username like '%${value}%'
其對應的實際sql操作語句:select * from user where username like'%五%'
也可以這樣寫:
select * from user where username like "%"#{value}"%" # value 可以換成haha
其對應的sql查詢語句是:select * from user where username like"%"'五'"%"
2.如果測試類中這樣寫:
List<User> list = session.selectList("test.findUserByUsername", "%王%");
User.xml這樣寫
select * from user where username like #{username}
其中username可以換成haha等其他名稱。
- 執行插入操作時,保存成功,但是id=0,需要解決id返回不正常的問題。如果剛保存用戶,此時用戶ID需要返回。執行完上面insert程序后,此時就能知道用戶的ID是多少,需要在插入之前補充語句:
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
select LAST_INSERT_ID()
</selectKey>