MyBatis概述和Hello示例程式以及傳統的CRUD
目錄
4、在src目錄建立mybatis-config.xml核心配置檔案
在工程下的config資料夾中建立 "log4j.properties"檔案
1.MyBatis概述
1、mybatis簡介
MyBatis 是支援定製化 SQL、儲存過程以及高階對映的優秀的持久層框架。
MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。
MyBatis可以使用簡單的XML或註解用於配置和原始對映,將介面和Java的POJO(Plain Old Java Objects,普通的Java物件)對映成資料庫中的記錄.
2、mybatis歷史
原是apache的一個開源專案iBatis, 2010年6月這個專案由apache software foundation 遷移到了google code,隨著開發團隊轉投Google Code旗下,ibatis3.x正式更名為Mybatis ,程式碼於2013年11月遷移到Github(下載地址見後)。
iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAO)
3、為什麼要使用mybatis
MyBatis是一個半自動化的持久化層框架。
jdbc程式設計---當我們使用jdbc持久化的時候,sql語句被硬編碼到java程式碼中。這樣耦合度太高。程式碼不易於維護。在實際專案開發中會經常新增sql或者修改sql,這樣我們就只能到java程式碼中去修改。
Hibernate和JPA
長難複雜SQL,對於Hibernate而言處理也不容易
內部自動生產的SQL,不容易做特殊優化。
基於全對映的全自動框架,javaBean存在大量欄位時無法只對映部分欄位。導致資料庫效能下降。
對開發人員而言,核心sql還是需要自己優化
sql和java編碼分開,功能邊界清晰,一個專注業務、一個專注資料。
可以使用簡單的XML或註解用於配置和原始對映,將介面和Java的POJO對映成資料庫中的記錄。成為業務程式碼+底層資料庫的媒介
4.理解 SqlSession及其子父類的含義!
SqlSession的使用範圍
- SqlSession中封裝了對資料庫的操作,如:查詢、插入、更新、刪除等。
- SqlSession通過SqlSessionFactory建立。
- SqlSessionFactory是通過SqlSessionFactoryBuilder進行建立。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用於建立SqlSessionFacoty,SqlSessionFacoty一旦建立完成就不需要SqlSessionFactoryBuilder了,因為SqlSession是通過SqlSessionFactory建立的。所以可以將SqlSessionFactoryBuilder當成一個工具類使用,最佳使用範圍是方法範圍即方法體內區域性變數。
SqlSessionFactory
SqlSessionFactory是一個介面,介面中定義了openSession的不同過載方法,SqlSessionFactory的最佳使用範圍是整個應用執行期間,一旦建立後可以重複使用,通常以單例模式管理SqlSessionFactory。
SqlSession
SqlSession是一個面向使用者的介面,sqlSession中定義了資料庫操作方法。
每個執行緒都應該它自己的SqlSession例項。SqlSession的例項不能共享使用,它也是執行緒不安全的。因此最佳的範圍是請求或方法範圍。絕對不能將SqlSession例項的引用放在一個類的靜態欄位或例項欄位中。
2.MyBatis的Hello示例程式
1、建立一個數據庫和一個單表
drop database if exists mybatis;
create database mybatis;
use mybatis;
## 建立單表
####################################################################
create table t_user(
`id` int primary key auto_increment,
`last_name` varchar(50),
`sex` int
);
insert into t_user(`last_name`,`sex`) values('wsp168',1);
select * from t_user;
mysql資料庫、表 建立結果:
2、搭建mybatis開發環境
建立一個java工程
導 入 需 要 的 jar 包:
- log4j-1.2.17.jar
- mybatis-3.4.1.jar
- mysql-connector-java-5.1.7-bin.jar
3、建立Pojo物件User
不呼叫介面方法,直接對映到xml檔案中!
package com.webcode.pojo;
public class User {
private Integer id;
private String lastName;
private Integer sex;
public User(Integer id, String lastName, Integer sex) {
super();
this.id = id;
this.lastName = lastName;
this.sex = sex;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User [id=" + id + ", lastName=" + lastName + ", sex=" + sex + "]";
}
}
4、在src目錄建立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"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/webcode/pojo/UserMapper.xml"/>
</mappers>
</configuration>
配置檔案程式碼獲取方法
:
5、建立UserMapper.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名稱空間
取值一般有兩種情況:
一種情況是:使用javaBean的全類名
二種情況是:使用Mapper介面的全類名
-->
<mapper namespace="com.webcode.pojo.User">
<!--
select標籤用來配置一個select語句
id 用來配置一個唯一的標識
resultType 是查詢完之後一條記錄對應轉換成為的javaBean物件
#{id}是佔位符
-->
<select id="selectUserById" resultType="com.webcode.pojo.User">
select id,last_name lastName,sex from t_user where id = #{id}
</select>
</mapper>
6、傳統mybatis的hello world 示例程式碼
package com.webcode.pojo.test;
import java.io.IOException;
import java.io.InputStream;
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 com.webcode.pojo.User;
public class UserTest {
@Test
public void testselectUserById() throws IOException {
//從配置檔案讀取指定的資源,以輸入流的形式返回
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 通過sqlSessionFactoryBuilder建立SqlSessionFactory(從輸入流獲取連線條件,建立連線工廠)
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
System.out.println(sqlSessionFactory);
//從工廠中獲取一個連線(看成是資料庫連線池即可),相當於 以前的Connection物件,每次用來都用關閉
SqlSession openSession = sqlSessionFactory.openSession();
try {
/*由相對路徑對映到xml檔案中的id,調動執行sql語句,
並以resultType定義的型別返回到請求端或者是客戶端*/
User user = openSession.selectOne("com.webcode.pojo.User.selectUserById",1);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
openSession.close();//釋放資源
}
}
}
列印結果: User [id=1, lastName=wsp168, sex=1]
程式碼流程:
關於Mybatis的配置檔案提示功能:
關於log4j的提示:
如果不想看到,解決方案為:
只要在應用的classpath中建立一個名稱為log4j.properties的檔案, 檔案的具體內容如下:
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 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
注意:
7.加入log4j配置
匯入‘log4j-1.2.17.jar’包
在工程下的config資料夾中建立 "log4j.properties"檔案
\u4E0B\uFF1A
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
# 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
列印結果:
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
[email protected]2929
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1585787493.
DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
DEBUG [main] - ==> Preparing: select id,last_name lastName,sex from t_user where id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
User [id=1, lastName=wsp168, sex=1]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
DEBUG [main] - Closing JDBC Connection [[email protected]]
DEBUG [main] - Returned connection 1585787493 to pool.
3、傳統方式mybatis的增,刪,改,查實現
UserDao:
package com.webcode.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.webcode.pojo.User;
/**
* @author 鮀城小帥
* */
/**
*
* 注意:在建立連線時,底層自動對事務commit做了false定義,而沒有提交的事務會自動回滾。
* 在執行CRUD時要手動提交事務,即,在執行語句後,session.commit();
* */
public class UserDao {
private SqlSessionFactory sqlSessionFactory;
/*
* 建立sql會話工廠方法
* */
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
/*
* 根據id查詢使用者
* */
public User queryUserById(Integer id) {
SqlSession openSession = sqlSessionFactory.openSession();
try {
return openSession.selectOne("com.webcode.pojo.User.selectUserById",id);
} catch (Exception e) {
e.printStackTrace();
} finally {
openSession.close();//釋放資源
}
return null;
}
/*
* 查詢所有使用者
* */
public List<User> queryUsers(){
SqlSession session = sqlSessionFactory.openSession();
try {
return session.selectList("com.webcode.pojo.User.queryUsers");
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();//釋放資源
}
return null;
}
/*
* 新增使用者
* */
public int saveUser(User user) {
SqlSession session = sqlSessionFactory.openSession();
try {
int result = session.insert("com.webcode.pojo.User.saveUser",user);
session.commit();//提交事務
return result;
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();//釋放資源
}
return -1;
}
/*
* 根據id刪除使用者
* */
public int deleteUserById(Integer id) {
SqlSession openSession = sqlSessionFactory.openSession();
try {
int delete = openSession.delete("com.webcode.pojo.User.deleteUserById",id);
openSession.commit();//手動提交事務
return delete;
} catch (Exception e) {
e.printStackTrace();
} finally {
openSession.close();//釋放資源
}
return -1;
}
/*
* 修改使用者
* */
public int updateUser(User user) {
SqlSession openSession = sqlSessionFactory.openSession();
try {
int update = openSession.update("com.webcode.pojo.User.updateUsers",user);
openSession.commit();//手動提交事務
return update;
} catch (Exception e) {
// TODO: handle exception
}finally {
openSession.close();//釋放資源
}
return -1;
}
}
編寫UserMapper.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名稱空間
取值一般有兩種情況:
一種情況是:使用javaBean的全類名
二種情況是:使用Mapper介面的全類名
-->
<mapper namespace="com.webcode.pojo.User">
<!--
select標籤用來配置一個select語句
id 用來配置一個唯一的標識
resultType 是查詢完之後一條記錄對應轉換成為的javaBean物件
#{id}是佔位符
-->
<select id="selectUserById" resultType="com.webcode.pojo.User">
select id,last_name lastName,sex from t_user where id = #{id}
</select>
<!-- 查詢全部的User物件 -->
<select id="queryUsers" resultType="com.webcode.pojo.User">
select id,last_name lastName,sex from t_user
</select>
<!-- parameterTypr引數型別(可選)
useGeneratedKeys="true" 使用(或返回)資料庫生成的主鍵
keyProperty="id" 把資料庫返回的主鍵值注入到bean物件的id屬性中
-->
<insert id="saveUser" parameterType="com.webcode.pojo.User" >
<!--
selectKey標籤可以定義一些查詢語句,這些語句可以選擇性地在大標籤的sql語句之前或之後執行
我們希望,通過執行一個查詢,把最後一次生成的id返回。
order屬性配置執行的順序
BEFORE 之前
AFTER 之後
keyProperty="id" 把資料庫返回的主鍵值注入到bean物件的id屬性中
resultType="int" 設定selectKey查詢之後返回的型別是什麼 int 表示Integer型別
-->
<selectKey order="AFTER" keyProperty="id" resultType="int">
select last_insert_id()
</selectKey>
insert into t_user (`last_name`,`sex`) values(#{lastName},#{sex})
</insert>
<!-- <insert id="saveUser" parameterType="com.webcode.pojo.User" -->
<!-- useGeneratedKeys="true" keyProperty="id"> -->
<!-- insert into t_user (`last_name`,`sex`) values(#{lastName},#{sex}) -->
<!-- </insert> -->
<!-- 根據id刪除一個使用者 -->
<delete id="deleteUserById" parameterType="int">
delete from t_user where id=#{id}
</delete>
<update id="updateUser" parameterType="com.webcode.pojo.User">
update t_user set last_name = #{lastName},sex=#{sex} where id=#{id}
</update>
</mapper>
編寫UserDao測試
package com.webcode.dao.test;
import static org.junit.Assert.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
import com.webcode.dao.UserDao;
import com.webcode.pojo.User;
/**
* @author 鮀城小帥
* */
public class UserDaoTest {
private static UserDao userDao;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsStream("mybatis-config.xml"));
userDao = new UserDao();
userDao.setSqlSessionFactory(sqlSessionFactory);
}
@Test
public void testQueryUserById() {
System.out.println(userDao.queryUserById(1));
}
@Test
public void testQueryUsers() {
userDao.queryUsers().forEach(System.out::println);
}
@Test
public void testSaveUser() {
userDao.saveUser(new User(null, "xxx", 1));
}
@Test
public void testDeleteUserById() {
userDao.deleteUserById(3);
}
@Test
public void testUpdateUser() {
userDao.updateUser(new User(3,"aaa",0));
}
}
插入記錄並返回主鍵
列印結果: