MyBatis 框架

MyBatis源自apache的一個(gè)開(kāi)源項(xiàng)目iBatis,2010年這個(gè)項(xiàng)目由apache software foundation遷移到了google code,并且改名為MyBatis。2013年11月遷移到Github。

MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息,將接口和 Java 的 POJO(Plain Ordinary Java Object,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。

有下列特點(diǎn):

  • MyBatis是一個(gè)半ORM(對(duì)象關(guān)系映射)框架,底層封裝了JDBC,是程序員在開(kāi)發(fā)時(shí)只需要關(guān)注SQL語(yǔ)句本身,不需要花費(fèi)精力去處理加載驅(qū)動(dòng)、創(chuàng)建連接、創(chuàng)建statement等繁雜的過(guò)程。使得程序員可以花更多的精力放到業(yè)務(wù)開(kāi)發(fā)中。另外,程序員直接編寫原生態(tài)sql,嚴(yán)格控制sql執(zhí)行性能,靈活度高。

  • MyBatis 可以使用簡(jiǎn)單的 XML文件 或注解方式來(lái)配置和映射原生信息,將 POJO映射成數(shù)據(jù)庫(kù)中的記錄,避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。

  • 通過(guò)xml 文件或注解的方式將要執(zhí)行的各種 statement 配置起來(lái),并通過(guò)java對(duì)象和 statement中sql的動(dòng)態(tài)參數(shù)進(jìn)行映射生成最終執(zhí)行的sql語(yǔ)句,最后由MyBatis 框架執(zhí)行sql并將結(jié)果映射為java對(duì)象并返回。(從執(zhí)行sql到返回result的過(guò)程)。

運(yùn)作機(jī)制為:

  • 加載配置:配置來(lái)源于兩個(gè)地方,一處是配置文件,一處是Java代碼的注解,將SQL的配置信息加載成為一個(gè)個(gè)MappedStatement對(duì)象(包括了傳入?yún)?shù)映射配置、執(zhí)行的SQL語(yǔ)句、結(jié)果映射配置),存儲(chǔ)在內(nèi)存中。

  • SQL解析:當(dāng)API接口層接收到調(diào)用請(qǐng)求時(shí),會(huì)接收到傳入SQL的ID和傳入對(duì)象(可以是Map、JavaBean或者基本數(shù)據(jù)類型),Mybatis會(huì)根據(jù)SQL的ID找到對(duì)應(yīng)的MappedStatement,然后根據(jù)傳入?yún)?shù)對(duì)象對(duì)MappedStatement進(jìn)行解析,解析后可以得到最終要執(zhí)行的SQL語(yǔ)句和參數(shù)。

  • SQL執(zhí)行:將最終得到的SQL和參數(shù)拿到數(shù)據(jù)庫(kù)進(jìn)行執(zhí)行,得到操作數(shù)據(jù)庫(kù)的結(jié)果。

  • 結(jié)果映射:將操作數(shù)據(jù)庫(kù)的結(jié)果按照映射的配置進(jìn)行轉(zhuǎn)換,可以轉(zhuǎn)換成HashMap、JavaBean或者基本數(shù)據(jù)類型,并將最終結(jié)果返回。

開(kāi)發(fā)環(huán)境搭建

軟件 版本
HGDB 安全版V4、企業(yè)版v5及以上版本
JDK 1.6、1.7、1.8
Java IDE Eclipse、IntelliJ IDEA
MyBatis 3.5.2

前提準(zhǔn)備

要使用 MyBatis, 只需將 mybatis-x.x.x.jar 文件置于類路徑(classpath)中即可。

如果使用 Maven 來(lái)構(gòu)建項(xiàng)目,則需將下面的依賴代碼置于 pom.xml 文件中:

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>

示例項(xiàng)目

結(jié)構(gòu)圖如下:

image-20220419213239184

主要文件介紹

pom.xml:導(dǎo)入依賴的jar包

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!--highgo jdbc-->
<dependency>
<groupId>com.highgo</groupId>
<artifactId>HgdbJdbc</artifactId>
<version>6.2.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--Spring操作數(shù)據(jù)庫(kù)需要一個(gè)spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>

mybatis-config.xml:編寫全局配置文件(主要是配置數(shù)據(jù)源信息)

<?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>
<typeAliases>
<package name="com.highgo.pojo"/>
</typeAliases>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.highgo.jdbc.Driver"/>
<property name="url" value="jdbc:highgo://192.168.2.5:5866/test"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper class="com.highgo.mapper.UserMapper"/>
</mappers>
</configuration>

User.java:創(chuàng)建一個(gè)pojo類

package com.highgo.pojo;
import lombok.*;

import java.util.Date;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private int id;
private String name;
private Date birthday;

}

UserMapper.xml:編寫mapper映射文件(編寫SQL)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.highgo.mapper.UserMapper">
<select id="selectAll" resultType="User">
select * from test_user;
</select>

<insert id="addUser" parameterType="com.highgo.pojo.User">
INSERT INTO test_user (name,birthday) VALUES (#{name},#{birthday});
</insert>

<delete id="deleteUser" parameterType="int">
DELETE FROM test_user WHERE id = #{id};
</delete>

<select id="findByName" parameterType="string" resultType="User">
SELECT * FROM test_user WHERE name like '%${value}%';
</select>

</mapper>

UserMapper.java:創(chuàng)建一個(gè)mapper接口

package com.highgo.mapper;
import com.highgo.pojo.User;
import java.util.List;

public interface UserMapper {
public List<User> selectAll();

public int addUser(User user);

public int deleteUser(int id);

List<User> findByName(String value);
}

MyTest.java:測(cè)試代碼

public class MyTest {

private SqlSessionFactory sqlSessionFactory;

@Before
public void init() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
}

@Test
public void insertTest() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setName("Tomcat");
user.setBirthday(new Date());
mapper.addUser(user);
sqlSession.commit();
}

@Test
public void findAllTest() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.selectAll();
for (User user : userList) {
System.out.println(user);
}
}

@Test
public void findByName() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.findByName("張");
for (User user : userList) {
System.out.println(user);
}
}

}

執(zhí)行結(jié)果:

image-20220516182656720

image-20220516182719554

注意事項(xiàng)

1、mapper接口和mapper.xml之間需要遵循一定規(guī)則,才能成功的讓MyBatis 將mapper接口和mapper.xml綁定起來(lái)

  • mapper接口的全限定名,要和mapper.xml的namespace屬性一致
  • mapper接口中的方法名要和mapper.xml中的SQL標(biāo)簽的id一致
  • mapper接口中的方法入?yún)㈩愋?,要和mapper.xml中SQL語(yǔ)句的入?yún)㈩愋鸵恢?/li>
  • mapper接口中的方法出參類型,要和mapper.xml中SQL語(yǔ)句的返回值類型一致

2、Map傳值

在 MyBatis 的 mapper.xml 中我們很多時(shí)候喜歡使用 Map 傳值,如下:

<select id= "getList" resultType= "java.util.Map" parameterType = "java.util.Map" >
SELECT user_id, user_name FROM sysuser
</select>

這里我們使用 Map 作為 resultType 和 parameterType,為提高代碼可維護(hù)性,建議使用實(shí)體類傳值,改為如下:

<select id= "getList" resultType= "com.entity.SysUser" parameterType = "com.entity.SysUser">
SELECT user_id, user_name FROM sysuser
</select>

3、MyBatis 分頁(yè)

方式一:直接在 mapper.xml 文件中寫的分頁(yè)語(yǔ)法

如下:

<select id= "getList" parameterType= "SysUser" resultMap= "SysUser" >
SELECT user_id, user_name FROM sysuser limit #{pageSize} offset #{pageIndex}
</select>

需要將所有用到分頁(yè)的地方都修改為 HGDB 支持的語(yǔ)法。因?yàn)槊總€(gè)文件都需要替換,因此管理起來(lái)還是不方便。

方式二:使用分頁(yè)插件

在使用 MyBatis 框架時(shí),分頁(yè)方式可以用攔截器實(shí)現(xiàn)。比如Pagehelper分頁(yè)插件,具體使用請(qǐng)參考Pagehelper。Pagehelper進(jìn)行 HGDB 分頁(yè)時(shí),需要將 Pagehelper的 helperDialect配置為“postgresql”,或者修改 Pagehelper的分頁(yè) sql 為 HGDB 支持的語(yǔ)法。

在不同版本的 Pagehelper中,有些版本可能本身沒(méi)有實(shí)現(xiàn)“postgresql”這個(gè)配置;此時(shí)可考慮更換 Pagehelper版本,或者自己去用代碼實(shí)現(xiàn)“postgresql”配置,或者直接修改 Pagehelper的分頁(yè) sql。