1琅摩、簡(jiǎn)介
MyBatis 本是apache的一個(gè)開(kāi)源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation
遷移到了google code,并且改名為MyBatis 镜撩。2013年11月遷移到Github。
iBATIS一詞來(lái)源于“internet”和“abatis”的組合队塘,是一個(gè)基于Java的持久層框架袁梗。
MyBatis 支持定制化 SQL宜鸯、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC代碼和手
動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集遮怜。MyBatis 可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息淋袖,將
接口和 Java的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。
2锯梁、添加依賴(lài)
使用MyBatis與數(shù)據(jù)庫(kù)進(jìn)行交互需要添加兩個(gè)依賴(lài):一個(gè)是數(shù)據(jù)庫(kù)的驅(qū)動(dòng)即碗,不同的數(shù)據(jù)庫(kù)需要不同的驅(qū)動(dòng)。另一個(gè)是MyBatis的依賴(lài):
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
上面添加的數(shù)據(jù)庫(kù)依賴(lài)是MySQL的陌凳,具體看你用的是什么數(shù)據(jù)庫(kù)就添加對(duì)應(yīng)的依賴(lài)就可以了剥懒。
3、xml文件配置
mybatis.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.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="huwenlong"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper.xml"/>
</mappers>
</configuration>
mybatis.xml文件位于resources目錄下合敦,它的根節(jié)點(diǎn)是configuration初橘,環(huán)境默認(rèn)為開(kāi)發(fā)環(huán)境,數(shù)據(jù)源為連接池蛤肌,MyBatis自帶連接池壁却。四個(gè)屬性根據(jù)自己使用的數(shù)據(jù)庫(kù)進(jìn)行設(shè)置,我使用的是MySQL 8.0所以驅(qū)動(dòng)是com.mysql.cj.jdbc.Driver裸准,如果你使用的是8.0以下版本則應(yīng)該是com.mysql.jdbc.Driver。然后就是數(shù)據(jù)庫(kù)名赔硫、用戶(hù)名與密碼炒俱,填寫(xiě)對(duì)應(yīng)的就好。最后一個(gè)mappers是映射關(guān)系爪膊,resource是一個(gè)文件权悟。
mapper.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.qianfeng.pojo.User">
<select id="selectUsers" resultType="com.qianfeng.pojo.User">
select * from user
</select>
<select id="selectUser" resultType="com.qianfeng.pojo.User">
select * from user where userName = #{userName} and password = #{password}
</select>
<select id="selectUserCount" resultType="int">
select count(1) from user
</select>
<select id="selectUsersByPage" resultType="com.qianfeng.pojo.User">
select * from user limit #{startIndex},#{pageSize}
</select>
<insert id="saveUser" >
insert into user values (default ,#{userName},#{password},#{age},#{address})
</insert>
<delete id="deleteUser">
delete from user where id = #{id}
</delete>
<update id="updateUser">
update user set userName = #{userName},password = #{password},age = #{age},address = #{address} where id = #{id}
</update>
</mapper>
這個(gè)文件最重要的是namespace以及每一個(gè)項(xiàng)目的id,前者規(guī)定了命名空間推盛,可以自己定義峦阁,后者是區(qū)分每一條語(yǔ)句的id,也可以自己定義耘成,但要保證namespace+id全局唯一榔昔,使用的時(shí)候要對(duì)應(yīng)。#{}包裹的是占位符瘪菌,我們使用的時(shí)候需要傳參撒会。resultType是結(jié)果類(lèi)型。
4师妙、編寫(xiě)測(cè)試代碼
User.java
package com.qianfeng.pojo;
public class User {
private int id;
private String userName;
private String password;
private int age;
private String address;
public User() {
}
public User(int id, String userName,String password, int age, String address) {
this.password = password;
this.id = id;
this.userName = userName;
this.age = age;
this.address = 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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("id=").append(id);
sb.append(", userName='").append(userName).append('\'');
sb.append(", password='").append(password).append('\'');
sb.append(", age=").append(age);
sb.append(", address='").append(address).append('\'');
sb.append('}');
return sb.toString();
}
}
User類(lèi)是一個(gè)POJO诵肛,有5個(gè)成員,每個(gè)成員要與數(shù)據(jù)庫(kù)的user表的每個(gè)字段一一對(duì)應(yīng)默穴。
UserTest.java
package com.qianfeng.pojo;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
public class UserTest {
private SqlSessionFactory sf = null;
private SqlSession ss = null;
@Before
public void setUp() throws Exception {
sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
ss = sf.openSession(true);
}
@Test
public void testSelectUsers(){
List<User> users = ss.selectList("com.qianfeng.pojo.User.selectUsers");
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectUser(){
User user = new User();
user.setUserName("王五");
user.setPassword("888888");
User user1 = ss.selectOne("com.qianfeng.pojo.User.selectUser",user);
System.out.println(user1);
}
@Test
public void testSelectUserCount(){
int i = ss.selectOne("com.qianfeng.pojo.User.selectUserCount");
System.out.println(i);
}
@Test
public void testSelectUsersByPage(){
Map<String,Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",5);
List<User> users = ss.selectList("com.qianfeng.pojo.User.selectUsersByPage",map);
for (User user : users) {
System.out.println(user);
}
}
@Test
public void saveUser(){
User user = new User(0,"李四","1234567",20,"湖北省武漢市");
int i = ss.insert("com.qianfeng.pojo.User.saveUser",user);
System.out.println(i);
}
@Test
public void deleteUser(){
int i = ss.delete("com.qianfeng.pojo.User.deleteUser",1);
System.out.println(i);
}
@Test
public void updateUser(){
User user = new User(2,"王五","888888",21,"安徽省合肥市");
int i = ss.update("com.qianfeng.pojo.User.updateUser",user);
System.out.println(i);
}
@After
public void tearDown() throws Exception {
if(ss!=null){
ss.close();
ss = null;
}
}
}
這個(gè)測(cè)試類(lèi)實(shí)現(xiàn)了MyBatis的增刪改查操作怔檩,由于創(chuàng)建SqlSessionFactory與SqlSession與銷(xiāo)毀SqlSession的操作每個(gè)方法都需要執(zhí)行褪秀,所以把它們單獨(dú)提出來(lái)分別放在setUp與tearDown方法中。
SqlSession中有很多方法可以用于數(shù)據(jù)庫(kù)的增刪改查操作薛训,每個(gè)方法的第一個(gè)參數(shù)都是String類(lèi)型statement媒吗,這個(gè)值是我們之前在mapper.xml文件中的"namespace.id"。第二個(gè)參數(shù)是一個(gè)Object類(lèi)型的對(duì)象许蓖,用于一些條件蝴猪,比如條件查詢(xún),插入值等膊爪,select方法還有第三個(gè)參數(shù)RowBounds參數(shù)自阱,這個(gè)參數(shù)用于分頁(yè)。
5米酬、與Hibernate的比較
兩者都是非常流行的ORM框架(Object Relational Mapping對(duì)象關(guān)系映射)沛豌。Hibernate的O/R Mapping實(shí)現(xiàn)了POJO 和數(shù)據(jù)庫(kù)表之間的映射,以及SQL的自動(dòng)生成和執(zhí)行赃额。相對(duì)Hibernate“O/R”而言加派,Mybatis 是一種“Sql Mapping”的ORM實(shí)現(xiàn)
Hibernate的真正掌握要比MyBatis困難,Hibernate比mybatis更加重量級(jí)一些跳芳。
Mybatis需要我們手動(dòng)編寫(xiě)SQL語(yǔ)句芍锦,回歸最原始的方式,所以可以按需求指定查詢(xún)的字段飞盆,提高程序的查詢(xún)效率娄琉。Hibernate也可以自己寫(xiě)SQL語(yǔ)句來(lái)指定需要查詢(xún)的字段,但這樣破壞了Hibernate封裝以及簡(jiǎn)潔性吓歇。
MyBatis由于所有的sql語(yǔ)句都是依賴(lài)數(shù)據(jù)庫(kù)書(shū)寫(xiě)的孽水,所以擴(kuò)展性遷移性比較差。Hibeinate通用性比較強(qiáng)城看。
兩者的緩存有相同之處:二級(jí)緩存除了采用系統(tǒng)默認(rèn)的緩存機(jī)制外女气,都可以通過(guò)實(shí)現(xiàn)你自己的緩存或?yàn)槠渌谌骄彺娣桨福瑒?chuàng)建適配器來(lái)完全覆蓋緩存行為测柠,也有不同之處:Hibernate的二級(jí)緩存配置在SessionFactory生成的配置文件中進(jìn)行詳細(xì)配置炼鞠,然后再在具體的表-對(duì)象映射中配置是那種緩存。MyBatis的二級(jí)緩存配置都是在每個(gè)具體的表-對(duì)象映射中進(jìn)行詳細(xì)配置鹃愤,這樣針對(duì)不同的表可以自定義不同的緩存機(jī)制簇搅。并且Mybatis可以在命名空間中共享相同的緩存配置和實(shí)例,通過(guò)Cache-ref來(lái)實(shí)現(xiàn)软吐。