1 數據庫操作框架的歷程
1.1 JDBC
JDBC(Java Data Base Connection,java數據庫連接)是一種用於執行SQL語句的Java API,可以爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序
優點:運行期:快捷、高效
缺點:編輯期:代碼量大、繁瑣異常處理、不支持數據庫跨平臺
1.2 DBUtils
DBUtils是Java編程中的數據庫操作實用工具,小巧簡單實用
DBUtils封裝了對JDBC的操作,簡化了JDBC操作,可以少寫代碼
DBUtils三個核心功能介紹
QueryRunner中提供對sql語句操作的API
ResultSetHandler接口,用於定義select操作後,怎樣封裝結果集
DBUtils類,它就是一個工具類,定義了關閉資源與事務處理的方法
1.3 Hibernate
Hibernate 是由 Gavin King 於 2001 年創建的開放源代碼的對象關係框架。它強大且高效的構建具有關係對象持久性和查詢服務的 Java 應用程序
Hibernate 將 Java 類映射到數據庫表中,從 Java 數據類型中映射到 SQL 數據類型中,並把開發人員從 95% 的公共數據持續性編程工作中解放出來
Hibernate 是傳統 Java 對象和數據庫服務器之間的橋樑,用來處理基於 O/R 映射機制和模式的那些對象。
1.3.1 Hibernate優點
Hibernate 使用 XML 文件來處理映射 Java 類別到數據庫表格中,並且不用編寫任何代碼
爲在數據庫中直接儲存和檢索 Java 對象提供簡單的 APIs
如果在數據庫中或任何其它表格中出現變化,那麼僅需要改變 XML 文件屬性
抽象不熟悉的 SQL 類型,併爲我們提供工作中所熟悉的 Java 對象
Hibernate 不需要應用程序服務器來操作
操控你數據庫中對象複雜的關聯
最小化與訪問數據庫的智能提取策略
提供簡單的數據詢問
數據移植性強
1.3.2 Hibernate缺點
過度工程化,性能較差,難以優化
學習難度較大
無法進行細緻操作,例如減少查詢出的列數
緩存機制不如redis
尋找bug困難
批量數據操作需要大量的內存空間而且執行過程中需要的對象太多
1.4 JDBCTemplate
JdbcTemplate針對數據查詢提供了多個重載的模板方法,你可以根據需要選用不同的模板方法。如果你的查詢很簡單,僅僅是傳入相應SQL或者相關參數,然後取得一個單一的結果,那麼你可以選擇如下一組便利的模板方法
優點:運行期:高效、內嵌Spring框架中、支持基於AOP的聲明式事務
缺點:必須於Spring框架結合在一起使用、不支持數據庫跨平臺、默認沒有緩存
2 Mybatis
MyBatis 是一款優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來將原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)映射成數據庫中的記錄
優點
與JDBC相比,減少了50%的代碼量
最簡單的持久化框架,簡單易學
SQL代碼從程序代碼中徹底分離出來,可以重用
提供XML標籤,支持編寫動態SQL
提供映射標籤,支持對象與數據庫的ORM字段關係映射:
O就是Object,即java對象
R表示關係,其實就是數據庫中的表
M表示他們之間的映射關係
缺點
SQL語句編寫工作量大,熟練度要高
數據庫移植性比較差,如果需要切換數據庫的話,SQL語句會有很大的差異
3 第一個Mybatis項目
創建普通的maven項目
添加pom依賴
<?xml version="1.0" encoding="UTF-8"?>
< project xmlns = " http://maven.apache.org/POM/4.0.0"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0.0</ modelVersion>
< groupId> org.example</ groupId>
< artifactId> mybatis</ artifactId>
< version> 1.0-SNAPSHOT</ version>
< dependencies>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis</ artifactId>
< version> 3.5.4</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 8.0.16</ version>
</ dependency>
< dependency>
< groupId> log4j</ groupId>
< artifactId> log4j</ artifactId>
< version> 1.2.17</ version>
</ dependency>
< dependency>
< groupId> junit</ groupId>
< artifactId> junit</ artifactId>
< version> 4.13</ version>
< scope> test</ scope>
</ dependency>
</ dependencies>
</ project>
創建對應的數據表
create table emp select * from scott. emp;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
DROP TABLE IF EXISTS ` dept` ;
CREATE TABLE ` dept` (
` deptno` int ( 2 ) NOT NULL ,
` dname` varchar ( 15 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
` loc` varchar ( 15 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY ( ` deptno` ) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO ` dept` VALUES ( 10 , 'ACCOUNTING' , 'NewYork' ) ;
INSERT INTO ` dept` VALUES ( 20 , 'RESEARCH' , 'Dallas' ) ;
INSERT INTO ` dept` VALUES ( 30 , 'SALES' , 'Chicago' ) ;
INSERT INTO ` dept` VALUES ( 40 , 'OPERATIONS' , 'Boston' ) ;
DROP TABLE IF EXISTS ` emp` ;
CREATE TABLE ` emp` (
` empno` int ( 4 ) NOT NULL COMMENT '僱員編號' ,
` ename` varchar ( 10 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
` job` varchar ( 10 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
` mgr` int ( 4 ) NULL DEFAULT NULL ,
` hiredate` date NULL DEFAULT NULL ,
` sal` decimal ( 7 , 0 ) NULL DEFAULT NULL ,
` comm` decimal ( 7 , 0 ) NULL DEFAULT NULL ,
` deptno` int ( 2 ) NULL DEFAULT NULL ,
PRIMARY KEY ( ` empno` ) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO ` emp` VALUES ( 7369 , 'SMITH' , 'CLERK' , 7902 , '1980-12-17' , 800 , NULL , 20 ) ;
INSERT INTO ` emp` VALUES ( 7499 , 'ALLEN' , 'SALESMAN' , 7698 , '1981-02-20' , 1600 , 300 , 30 ) ;
INSERT INTO ` emp` VALUES ( 7521 , 'WARD' , 'SALESMAN' , 7698 , '1981-02-22' , 1250 , 500 , 30 ) ;
INSERT INTO ` emp` VALUES ( 7566 , 'JONES' , 'MANAGER' , 7839 , '1981-04-02' , 2975 , NULL , 20 ) ;
INSERT INTO ` emp` VALUES ( 7654 , 'MARTIN' , 'SALESMAN' , 7698 , '1981-09-28' , 1250 , 1400 , 30 ) ;
INSERT INTO ` emp` VALUES ( 7698 , 'BLAKE' , 'MANAGER' , 7839 , '1981-05-01' , 2850 , NULL , 30 ) ;
INSERT INTO ` emp` VALUES ( 7782 , 'CLARK' , 'MANAGER' , 7839 , '1981-06-09' , 2450 , NULL , 10 ) ;
INSERT INTO ` emp` VALUES ( 7788 , 'SCOTT' , 'ANALYST' , 7566 , '1987-07-13' , 3000 , NULL , 20 ) ;
INSERT INTO ` emp` VALUES ( 7839 , 'KING' , 'PRESIDENT' , NULL , '1981-11-17' , 5000 , NULL , 10 ) ;
INSERT INTO ` emp` VALUES ( 7844 , 'TURNER' , 'SALESMAN' , 7698 , '1981-09-08' , 1500 , 0 , 30 ) ;
INSERT INTO ` emp` VALUES ( 7876 , 'ADAMS' , 'CLERK' , 7788 , '1987-07-13' , 1100 , NULL , 20 ) ;
INSERT INTO ` emp` VALUES ( 7900 , 'JAMES' , 'CLERK' , 7698 , '1981-12-03' , 950 , NULL , 30 ) ;
INSERT INTO ` emp` VALUES ( 7902 , 'FORD' , 'ANALYST' , 7566 , '1981-12-03' , 3000 , NULL , 20 ) ;
INSERT INTO ` emp` VALUES ( 7934 , 'MILLER' , 'CLERK' , 7782 , '1982-01-23' , 1300 , NULL , 10 ) ;
DROP TABLE IF EXISTS ` salgrade` ;
CREATE TABLE ` salgrade` (
` grade` int ( 7 ) NULL DEFAULT NULL ,
` losal` int ( 7 ) NULL DEFAULT NULL ,
` hisal` int ( 7 ) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO ` salgrade` VALUES ( 1 , 700 , 1200 ) ;
INSERT INTO ` salgrade` VALUES ( 2 , 1201 , 1400 ) ;
INSERT INTO ` salgrade` VALUES ( 3 , 1401 , 2000 ) ;
INSERT INTO ` salgrade` VALUES ( 4 , 2001 , 3000 ) ;
INSERT INTO ` salgrade` VALUES ( 5 , 3001 , 9999 ) ;
SET FOREIGN_KEY_CHECKS = 1 ;
Emp.java:表對應的實體類對象
package com. mashibing. bean;
import java. util. Date;
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private Double sal;
private Double common;
private Integer deptno;
public Emp ( ) {
}
public Emp ( Integer empno, String ename) {
this . empno = empno;
this . ename = ename;
}
public Emp ( Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double common, Integer deptno) {
this . empno = empno;
this . ename = ename;
this . job = job;
this . mgr = mgr;
this . hiredate = hiredate;
this . sal = sal;
this . common = common;
this . deptno = deptno;
}
public Integer getEmpno ( ) {
return empno;
}
public void setEmpno ( Integer empno) {
this . empno = empno;
}
public String getEname ( ) {
return ename;
}
public void setEname ( String ename) {
this . ename = ename;
}
public String getJob ( ) {
return job;
}
public void setJob ( String job) {
this . job = job;
}
public Integer getMgr ( ) {
return mgr;
}
public void setMgr ( Integer mgr) {
this . mgr = mgr;
}
public Date getHiredate ( ) {
return hiredate;
}
public void setHiredate ( Date hiredate) {
this . hiredate = hiredate;
}
public Double getSal ( ) {
return sal;
}
public void setSal ( Double sal) {
this . sal = sal;
}
public Double getCommon ( ) {
return common;
}
public void setCommon ( Double common) {
this . common = common;
}
public Integer getDeptno ( ) {
return deptno;
}
public void setDeptno ( Integer deptno) {
this . deptno = deptno;
}
@Override
public String toString ( ) {
return "Emp{" +
"empno=" + empno +
", ename='" + ename + '\'' +
", job='" + job + '\'' +
", mgr=" + mgr +
", hiredate=" + hiredate +
", sal=" + sal +
", common=" + common +
", deptno=" + deptno +
'}' ;
}
}
EmpDao.java:進行數據庫操作的dao層接口
package com. mashibing. dao;
import com. mashibing. bean. Emp;
public interface EmpDao {
public Emp findEmpByEmpno ( Integer empno) ;
}
mybatis-config.xml:resources下建立配置文件
<?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.cj.jdbc.Driver" />
< property name = " url" value = " jdbc:mysql://localhost:3306/demo?serverTimezone=UTC" />
< property name = " username" value = " root" />
< property name = " password" value = " c50hst" />
</ dataSource>
</ environment>
</ environments>
< mappers>
< mapper resource = " EmpDao.xml" />
</ mappers>
</ configuration>
EmpDao.xml:resource下建立映射文件,注意這個文件名要和Dao層的類名相同,我們不必自己再寫Dao層的具體實現
<?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">
< mapper namespace = " com.mashibing.dao.EmpDao" >
< select id = " findEmpByEmpno" resultType = " com.mashibing.bean.Emp" >
select * from emp where empno = #{empno}
</ select>
</ mapper>
log4j.properties:類路徑上添加
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.mashibing=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
MyTest.java:測試類
package com. mashibing. test;
import com. mashibing. bean. Emp;
import com. mashibing. dao. EmpDao;
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;
public class MyTest {
@Test
public void test01 ( ) {
String resource = "mybatis-config.xml" ;
InputStream inputStream = null;
try {
inputStream = Resources. getResourceAsStream ( resource) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ( ) . build ( inputStream) ;
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
Emp empByEmpno = null;
try {
EmpDao mapper = sqlSession. getMapper ( EmpDao. class ) ;
empByEmpno = mapper. findEmpByEmpno ( 7369 ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
sqlSession. close ( ) ;
}
System. out. println ( empByEmpno) ;
}
}
4 增刪改查的基本操作
EmpDao.java
package com. mashibing. dao;
import com. mashibing. bean. Emp;
public interface EmpDao {
public Emp findEmpByEmpno ( Integer empno) ;
public int updateEmp ( Emp emp) ;
public int deleteEmp ( Integer empno) ;
public int insertEmp ( Emp emp) ;
}
EmpDao.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">
< mapper namespace = " com.mashibing.dao.EmpDao" >
< select id = " findEmpByEmpno" resultType = " com.mashibing.bean.Emp" >
select * from emp where empno = #{empno}
</ select>
< insert id = " insertEmp" >
insert into emp(empno,ename) values(#{empno},#{ename})
</ insert>
< update id = " updateEmp" >
update emp set ename=#{ename} where empno = #{empno}
</ update>
< delete id = " deleteEmp" >
delete from emp where empno = #{empno}
</ delete>
</ mapper>
MyTest.java
package com. mashibing. test;
import com. mashibing. bean. Emp;
import com. mashibing. dao. EmpDao;
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. Before;
import org. junit. Test;
import java. io. IOException;
import java. io. InputStream;
public class MyTest {
SqlSessionFactory sqlSessionFactory = null;
@Before
public void init ( ) {
String resource = "mybatis-config.xml" ;
InputStream inputStream = null;
try {
inputStream = Resources. getResourceAsStream ( resource) ;
sqlSessionFactory= new SqlSessionFactoryBuilder ( ) . build ( inputStream) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
@Test
public void test01 ( ) {
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
Emp empByEmpno = null;
try {
EmpDao mapper = sqlSession. getMapper ( EmpDao. class ) ;
empByEmpno = mapper. findEmpByEmpno ( 7369 ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
sqlSession. close ( ) ;
}
System. out. println ( empByEmpno) ;
}
@Test
public void test02 ( ) {
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
EmpDao mapper = sqlSession. getMapper ( EmpDao. class ) ;
int zhangsan = mapper. insertEmp ( new Emp ( 1111 , "zhangsan" ) ) ;
System. out. println ( zhangsan) ;
sqlSession. commit ( ) ;
sqlSession. close ( ) ;
}
@Test
public void test03 ( ) {
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
EmpDao mapper = sqlSession. getMapper ( EmpDao. class ) ;
int zhangsan = mapper. updateEmp ( new Emp ( 1111 , "lisi" ) ) ;
System. out. println ( zhangsan) ;
sqlSession. commit ( ) ;
sqlSession. close ( ) ;
}
@Test
public void test04 ( ) {
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
EmpDao mapper = sqlSession. getMapper ( EmpDao. class ) ;
int zhangsan = mapper. deleteEmp ( 1111 ) ;
System. out. println ( zhangsan) ;
sqlSession. commit ( ) ;
sqlSession. close ( ) ;
}
}
5 註解的寫法
mybatis支持使用註解的方式,可以不用寫配置文件,但如果sql非常複雜,還是建議寫配置文件
EmpDaoAnnotation.java
package com. mashibing. dao;
import com. mashibing. bean. Emp;
import org. apache. ibatis. annotations. Delete;
import org. apache. ibatis. annotations. Insert;
import org. apache. ibatis. annotations. Select;
import org. apache. ibatis. annotations. Update;
public interface EmpDaoAnnotation {
@Select ( "select * from emp where empno = #{empno}" )
public Emp findEmpByEmpno ( Integer empno) ;
@Update ( "update emp set ename=#{ename} where empno = #{empno}" )
public int updateEmp ( Emp emp) ;
@Delete ( "delete from emp where empno = #{empno}" )
public int deleteEmp ( Integer empno) ;
@Insert ( "insert into emp(empno,ename) values(#{empno},#{ename})" )
public int insertEmp ( Emp emp) ;
}
mybatis-config.xml
< mappers>
< mapper resource = " EmpDao.xml" />
< mapper class = " com.mashibing.dao.EmpDaoAnnotation" />
</ mappers>
測試代碼
@Test
public void test06 ( ) {
SqlSession sqlSession = sqlSessionFactory. openSession ( ) ;
EmpDaoAnnotation mapper = sqlSession. getMapper ( EmpDaoAnnotation. class ) ;
int zhangsan = mapper. insertEmp ( new Emp ( 1111 , "zhangsan" ) ) ;
System. out. println ( zhangsan) ;
sqlSession. commit ( ) ;
sqlSession. close ( ) ;
}
6 配置文件詳解
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>
< properties resource = " db.properties" > </ properties>
< settings>
< setting name = " mapUnderscoreToCamelCase" value = " true" />
</ settings>
< typeAliases>
< package name = " com.mashibing.bean" />
</ typeAliases>
< typeHandlers>
< typeHandler handler = " " > </ typeHandler>
< package name = " " />
</ typeHandlers>
< objectFactory type = " " > </ objectFactory>
< plugins>
< plugin interceptor = " " > </ plugin>
</ plugins>
< environments default = " development" >
< environment id = " development" >
< transactionManager type = " JDBC" />
< dataSource type = " POOLED" >
< property name = " driver" value = " ${driverClassname}" />
< property name = " url" value = " ${url}" />
< property name = " username" value = " ${username}" />
< property name = " password" value = " ${password}" />
</ dataSource>
</ environment>
</ environments>
< databaseIdProvider type = " DB_VENDOR" >
< property name = " MySQL" value = " mysql" />
< property name = " SQL Server" value = " sqlserver" />
< property name = " Oracle" value = " orcl" />
</ databaseIdProvider>
< mappers>
< package name = " com.mashibing.dao" />
</ mappers>
</ configuration>