Hello word
1.1 JDBC 存在的问题
数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
使用 preparedStatement 向占位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便。
MyBatis 是一个优秀的持久层框架,它对 jdbc 的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建 statement、手动设置参数、结果集检索等 jdbc 繁杂的过程代码。Mybatis 通过 xml 或注解的方式将要执行的各种 statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过 java 对象和 statement 中的 sql 进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射成 java 对象并返回。
与其他的对象关系映射框架不同,MyBatis 并没有将 Java 对象与数据库表关联起来,而是将 Java 方法与 SQL 语句关联。MyBatis 允许用户充分利用数据库的各种功能,例如存储过程、视图、各种复杂的查询以及某数据库的专有特性。如果要对遗留数据库、不规范的数据库进行操作,或者要完全控制 SQL 的执行,MyBatis 是一个不错的选择。
HelloWorld
我们通过一个简单的 HelloWorld 先来看下 MyBatis 的基本用法。
首先来准备一个数据库:
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test01` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `test01`;
/*Table structure for table `user` */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
`address` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*Data for the table `user` */
insert into `user`(`id`,`username`,`address`) values (1,'java123','中国'),(3,'mybatis','石家庄'),(4,'张三','深圳'),(5,'李四','广州'),(6,'王五','北京');
接下来创建一个普通的 Maven 工程,不用创建 Web 工程,JavaSE 工程即可。项目创建完成后,添加 MyBatis 依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
接下来,在 Mapper 中,定义一个简单的查询方法,根据 id 查询一个用户:
<?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.java.lang">
<select id="getAllUser" resultType="com.java.lang.pojo.User"> /*resultType 为返回值类型*/
select * from user;
</select>
</mapper>
接下来,创建 MyBatis 配置文件:
<?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:///test01?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/java/lang/mapper/UserMapper.xml"/>
</mappers>
</configuration>
最后,我们来加载这个主配置文件:
public static void main(String[] args) throws IOException {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = factory.openSession();
List<User> list = sqlSession.selectList("com.java.lang.getAllUser");
for (User user : list) {
System.out.println(user);
}
sqlSession.close();
}
SqlSessionFactory 是一个接口,接口中定义了 openSession 的不同重载方法,SqlSessionFactory 的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理 SqlSessionFactory。
public class SqlSessionFactoryUtil {
private static SqlSessionFactory sqlSessionFactory;
private SqlSessionFactoryUtil() {
}
public static SqlSessionFactory getInstance() {
if (sqlSessionFactory == null) {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
return sqlSessionFactory;
}
}
pom 增加:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>/src/main/resources</directory>
</resource>
</resources>
</build>
基本的crud案例:
package test;
import com.java.lang.pojo.User;
import com.java.lang.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class MybatisTest {
private SqlSession session;
@Before
public void before() {
session = SqlSessionFactoryUtil.getInstance().openSession();
}
// 查询
@Test
public void select() {
List<User> list = session.selectList("com.java.lang.getAllUser");
for (User user : list) {
System.out.println(user);
}
}
// 删除
@Test
public void delete() {
int delete = session.delete("com.java.lang.deleteUserById", 1L);
System.out.println("delete = " + delete);
session.commit();
}
// 新增
@Test
public void insert() {
User user = new User();
user.setUserName("Lang");
user.setAddress("zg");
int insert = session.insert("com.java.lang.addUser", user);
System.out.println("insert = " + insert);
System.out.println("insert = " + insert);
session.commit();
}
// 修改
@Test
public void update() {
User user = new User();
user.setId(3L);
user.setAddress("zg");
user.setUserName("Lang");
int update = session.update("com.java.lang.updateUserById", user);
System.out.println("update = " + update);
session.commit();
}
@Test
public void selectUserById() {
User user = (User) session.selectOne("com.java.lang.findUserById", 3L);
System.out.println("user = " + user);
}
@After
public void after() {
session.close();
}
}
<?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.java.lang">
<select id="getAllUser" resultType="com.java.lang.pojo.User"> /*resultType 为返回值类型*/
select *
from user;
</select>
<insert id="addUser" parameterType="com.java.lang.pojo.User">
insert into user (username, address)
values (#{userName}, #{address});
</insert>
<delete id="deleteUserById" parameterType="Long">
delete
from user
where id = #{id};
</delete>
<update id="updateUserById" parameterType="com.java.lang.pojo.User">
update user
set username = #{userName}
where id = #{id};
</update>
<select id="findUserById" parameterType="Long" resultType="com.java.lang.pojo.User">
select *
from user
where id = #{id};
</select>
<!--当主键为UUID 时-->
<!-- <insert id="addUser" parameterType="com.java.lang.pojo.User">
<selectKey resultType="String" keyProperty="id" order="BEFORE">
select uuid();
</selectKey>
insert into user
(id,username,address)
values (#{id},#{username},#{address})
</insert>-->
</mapper>