一、引言
1.1 什么是框架?
软件的半成品,解决了软件开发过程当中的普适性问题,从而简化了开发步骤,提供了开发的效率。
1.2 什么是ORM框架?
- ORM(Object Relational Mapping)对象关系映射,将程序中的一个对象与表中的一行数据一一对应。
- ORM框架提供了持久化类与表的映射关系,在运行时参照映射文件的信息,把对象持久化到数据库中`。
1.3 使用JDBC完成ORM操作的缺点?
存在大量的冗余代码。
手工创建 Connection、Statement 等。
手工将结果集封装成实体对象。
查询效率低,没有对数据访问进行过优化(Not Cache)。
二、MyBatis框架
2.1 概念
- MyBatis本是Apache软件基金会的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了Google Code,并且改名为MyBatis 。2013年11月迁移到Github。
- MyBatis是一个优秀的基于Java的持久层框架,支持自定义SQL,存储过程和高级映射。
- MyBatis对原有JDBC操作进行了封装,几乎消除了所有JDBC代码,使开发者只需关注 SQL 本身。
- MyBatis可以使用简单的XML或Annotation来配置执行SQL,并自动完成ORM操作,将执行结果返回。
2.2 访问与下载
官方网站:http://www.mybatis.org/mybatis-3/
下载地址:https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.5.1
三、构建Maven项目
3.1 新建项目
使用IDEA打开已创建的文件夹目录 |
---|
image.png |
3.2 选择Maven目录
选择Maven项目 |
---|
image.png |
3.3 GAV坐标
GAV坐标 |
---|
image.png |
四、MyBatis入门案例【重点
】
4.1 pom.xml中引入MyBatis核心依赖
在pom.xml中引入相关依赖
<?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>com.qf</groupId>
<artifactId>mybatis-02</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
4.2 创建db.properties配置文件
在resources目录下创建db.properties
jdbc.url=jdbc:mysql://localhost:3306/java2002?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.cj.jdbc.Driver
4.3 创建log4j.properties配置文件
在resources目录下创建log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, 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
4.4 创建mybatis-config.xml配置文件
在resources目录下创建并配置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">
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置外部文件 -->
<properties resource="db.properties"></properties>
<!-- 配置别名 -->
<typeAliases>
<!-- <typeAlias type="com.qf.entity.User" alias="user"></typeAlias>-->
<package name="com.qf.entity"/>
</typeAliases>
<!-- 配置环境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
</configuration>
4.5 建表
create table t_user(
id int primary key auto_increment,
name varchar(50),
password varchar(50)
)default charset = utf8;
INSERT INTO t_user(NAME,PASSWORD) VALUES("jack","123");
INSERT INTO t_user(NAME,PASSWORD) VALUES("tom","456");
INSERT INTO t_user(NAME,PASSWORD) VALUES("rose","789");
4.6 定义实体类
定义所需CURD操作的实体类
package com.qf.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private Integer id;
private String name;
private String password;
}
4.7 定义DAO接口
根据所需DAO定义接口、以及方法
package com.qf.dao;
import com.qf.entity.User;
public interface UserDao {
public List<User> findAll();
}
4.8 编写Mapper.xml
在resources目录中下创建与Dao对应的路径和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">
<!--namespace = 所需实现的接口全限定名-->
<mapper namespace="com.qf.dao.UserDao">
<!--配置查询所有-->
<!--id = 所需重写的接口抽象方法名,resultType = 查询后所需返回的对象类型-->
<select id="findAll" resultType="user">
select * from t_user
</select>
</mapper>
4.9 注册Mapper
将Mapper.xml注册到mybatis-config.xml中
<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
<mappers>
<!--<mapper resource="com/qf/dao/UserDao.xml"/>-->
<!--<mapper class="com.qf.dao.UserDao"/>-->
<package name="com.qf.dao"/>
</mappers>
测试
在\src\test\java目录下创建测试类进行测试
package com.qf.demo;
import com.qf.dao.UserDao;
import com.qf.entity.User;
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.InputStream;
import java.util.List;
public class MybatisTest {
//查询所有
@Test
public void testfindAll()throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
五、MyBatis的CRUD操作【重点
】
7.1 在Dao添加方法
在src\main\java\com\qf\dao\UserDao.java中添加方法
package com.qf.dao;
import com.qf.entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.HashMap;
import java.util.List;
public interface UserDao {
public List<User> findAll();
public User findById(@Param("id") Integer id);
public void add(User user);
public void update(User user);
public void delete(String id);
//模糊查询1
public List<User> findByUserName1(String username);
//模糊查询2
public List<User> findByUserName2(String username);
//模糊查询3
public List<User> findByUserName3(String username);
//获取总记录数
public Integer getTotalCount();
//获取分页数据
public List<User> findPageData(HashMap<String,Integer> hashMap);
}
7.2 在Mapper.xml中添加对应的方法
在\src\main\resources\com\qf\dao\UserDao.xml中写对应的sql
<delete id="deleteUser" parameterType="int">
DELETE FROM t_users
WHERE id = #{id} <!--只有一个参数时,#{任意书写}-->
</delete>
7.3 测试
标签:< update id="" parameterType="" >
package com.qf.demo;
import com.qf.dao.UserDao;
import com.qf.entity.User;
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.InputStream;
import java.util.HashMap;
import java.util.List;
public class Demo {
//查询所有
@Test
public void testfindAll()throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
//查询单个
@Test
public void testfindById()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
User user = userDao.findById(1);
System.out.println(user);
//---------------------------------------------
session.close();
in.close();
}
//添加
@Test
public void testadd()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
User user = new User();
user.setName("张三");
user.setPassword("123");
userDao.add(user);
System.out.println(user.getId());
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
//修改
@Test
public void testupdate()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
User user = userDao.findById(4);
//user.setId(5);
user.setName("李四");
user.setPassword("456");
userDao.update(user);
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
//删除
@Test
public void testdelete()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
userDao.delete("4");
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
//模糊查询
@Test
public void testfindByUserName()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
String name = "张";
UserDao userDao = session.getMapper(UserDao.class);
//List<User> users = userDao.findByUserName1(name);
//List<User> users = userDao.findByUserName2("%" + name + "%");
List<User> users = userDao.findByUserName3(name);
for(User user : users){
System.out.println(user);
}
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
//查询总记录数
@Test
public void testgetTotalCount()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.getTotalCount());
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
//查询分页数据
@Test
public void testfindPageData()throws Exception {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
SqlSession session = factory.openSession();
//---------------------------------------------
UserDao userDao = session.getMapper(UserDao.class);
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("first",0);
hashMap.put("second",3);
List<User> users = userDao.findPageData(hashMap);
for(User user : users){
System.out.println(user);
}
//提交
session.commit();
//---------------------------------------------
session.close();
in.close();
}
}
六、Druid连接池
6.1 概念
Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和 SQL 解析器组成。该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL 翻译等,程序员可以通过定制来实现自己需要的功能。
6.2基准测试结果对比
JDBC-Conn Pool | 1 Thread | 2 threads | 5 threads | 10 threads | 20 threads | 50 threads |
---|---|---|---|---|---|---|
Druid | 898 | 1,191 | 1,324 | 1,362 | 1,325 | 1,459 |
tomcat-jdbc | 1,269 | 1,378 | 2,029 | 2,103 | 1,879 | 2,025 |
DBCP | 2,324 | 5,055 | 5,446 | 5,471 | 5,524 | 5,415 |
BoneCP | 3,738 | 3,150 | 3,194 | 5,681 | 11,018 | 23,125 |
jboss-datasource | 4,377 | 2,988 | 3,680 | 3,980 | 32,708 | 37,742 |
C3P0 | 10,841 | 13,637 | 10,682 | 11,055 | 14,497 | 20,351 |
Proxool | 16,337 | 16,187 | 18,310(Ex) | 25,945 | 33,706(Ex) | 39,501 (Ex) |
6.3 测试结论
- Druid 是性能最好的数据库连接池,tomcat-jdbc 和 druid 性能接近。
- Proxool 在激烈并发时会抛异常,不适用。
- C3P0 和 Proxool 都相当慢,影响 sql 执行效率。
- BoneCP 性能并不优越,采用 LinkedTransferQueue 并没有能够获得性能提升。
- 除了 bonecp,其他的在 JDK 7 上跑得比 JDK 6 上快。
- jboss-datasource 虽然稳定,但性能很糟糕。
6.4 配置pom.xml
引入Druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
6.5 创建DruidDataSourceFactory
在\src\main\java\com\qf\utils目录创建MyDruidDataSourceFactory来替换数据源
package com.qf.utils;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
public class MyDruidDataSourceFactory extends PooledDataSourceFactory {
public MyDruidDataSourceFactory() {
this.dataSource = new DruidDataSource();//替换数据源
}
}
6.6修改mybatis-config.xml
修改mybatis-config.xml中连接池的相关配置,指定Druid数据源
<!--连接池-->
<dataSource type="com.qf.utils.MyDruidDataSourceFactory">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
注意:< property name="属性名" />属性名必须与com.alibaba.druid.pool.DruidAbstractDataSource中一致。
七、PageHelper
7.1 概念
PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。
7.2 访问与下载
7.3 开发步骤
1.在pom.xml中引入PageHelper依赖。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.11</version>
</dependency>
2.在MyBatis-config.xml中添加< plugins >
<configuration>
<typeAliases></typeAliases>
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
<property name="supportMethodsArguments" value="true"/>
</plugin>
</plugins>
<environments>...</environments>
</configuration>
3.在测试类中添加方法进行测试
//查询分页
@Test
public void testfindByPage()throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
PageHelper.startPage(1,2);//设置当前页和每页显示记录数
List<User> users = userDao.findAll();
PageInfo<User> userPageInfo = new PageInfo<>(users);//封装到PageInfo对象中
System.out.println(userPageInfo);
//6.释放资源
session.close();
in.close();
}
7.4 PageInfo对象
PageInfo对象中包含了分页操作中的所有相关数据。
PageInfo结构图 |
---|
image.png |
7.5 注意事项
- 只有在PageHelper.startPage()方法之后的第一个查询会有执行分页。
- 分页插件不支持带有“for update”的查询语句。
- 分页插件不支持“嵌套查询”,由于嵌套结果方式会导致结果集被折叠,所以无法保证分页结果数量正确。。
网友评论