一 MyBatis框架
1 框架介绍
框架:对基础代码进行封装并提供相应的API,调用API可省去一些代码的编写,从而提高效率。一个好的框架一定是经过测试,自身的功能已经实现,可以完成特定的功能。
2 MyBatis 框架
MyBatis 框架是一款持久层框架,他集成了绝大部分的JDBC代码与手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解来配置和映射原生类型、接口和Java的domain对象,支持自定义sql,存储过程与高级映射
Mybatis的功能架构分为三层:
API接口层:提供给外部使用的接口API,通过这些本地API可操纵数据库。接口层接收到调用请求就会调用数据处理层完成具体的数据处理。
数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
基础支撑层:负责最基础的功能支撑,即连接管理、事务管理、配置加载和缓存处理,将这些共用的东西抽取出来作为最基础的组件。为上层提供最基础的支撑(数据处理层)
3 使用流程
① 编写 mybatis-config.xml 文件:配置连接数据的四要素(数据源),以及项目需要依赖的通用配置
② 编写 XxxMapper.xml文件:映射文件,编写SQL语句和类型映射
③ MyBatis 加载配置文件,创建SqlSessionFactory 对象(类似连接池)
④ 通过SqlSessionFactory来生产SqlSesson 对象 SqlSesson(类似 Connection连接对象)
⑤ 使用SqlSession即可执行CRUD操作
⑤ mybatis底层会进行数据处理,SQL执行以及结果集的处理
4 准备环境与测试
① 添加项目需要的 jar 包,或者导入对应的依赖
Lombok,可自动生成getter/setter/toString等方法
mysql-connector-java-5.1.36-bin.jar,Java语言连接MySQL数据库的驱动包,它提供了一系列的类和方法,可以用来执行创建和查询数据库、插入和更新数据、管理用户和权限等任务
mybatis-3.4.6.jar,MyBatis框架的核心包,它提供了一系列的类和方法,用于对数据库进行操作。MyBatis框架是一个持久层框架,它可以通过配置文件和映射文件来将SQL语句映射到Java对象,从而简化了数据库的操作。
② 数据库表
CREATE TABLE `t_employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`eid` varchar(10) NOT NULL,
`ename` varchar(6) NOT NULL,
`job` varchar(10) DEFAULT NULL,
`salary` int(10) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `eid` (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
③ 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Long id;
private String eid;
private String ename;
private String password;
private String job;
private Integer salary;
}
④ resources下编写主配置文件:mybatis-config.xml,拷贝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>
<!--配置日志-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--配置数据库连接信息-->
<environments default="dev">
<environment id="dev">
<!--配置事务管理模式-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源信息-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///web_crud"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="mappers/EmployeeMapper.xml"></mapper>
<!--扫描映射文件所在的包路径:mapper映射文件和mapper接口的路径需要保持一致,mapper路径需通过/分隔-->
</mappers>
</configuration>
⑤ 于mapper目录中,编写对应的mapper文件,拷贝约束信息,编写SQL语句,一个项目可以操作多张表,每张表都需要一个mapper配置文件来编写SQL语句每条SQL语句都需要有一个唯一的标识,这个唯一的标识由 namespace+sqlid 组成
使用namespace+sqlid就得到了保存用户信息的唯一标识,如:cn.tj.mybatis.mapper.EmployeeMapper.insert 之后可以通过标识找到这条SQL语句
<?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="employee">
<!--增加用户:id当前文件中sql标签的唯一标识-->
<insert id="insertEmployee">
insert into t_employee(eid,ename,job,salary,password) values(#{eid},#{ename},#{job},#{salary},#{password})
</insert>
</mapper>
⑥ 接口
public interface EmployeeDao {
//增加员工
void insertEmployee(Employee employee);
}
⑦ 实现类
public class EmployeeDaoImpl implements EmployeeDao {
@Override
public void insertEmployee(Employee employee) {
try {
//1.加载配置文件信息
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rs);
//2.创建sqlSession
//openSession()默认的时候是需要手动提交事务,如果设置自动提交事务需要参数设置为true
SqlSession sqlSession = factory.openSession(true);
//3.执行增加操作
sqlSession.insert("employee.insertEmployee",employee);
//手动提交事务
//sqlSession.commit();
//4.关闭对象
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
⑧ 测试类
public class EmployeeTest {
/*增加用户测试*/
@Test
public void employee_insert(){
EmployeeDao employeeDao=new EmployeeDaoImpl();
Employee employee = new Employee(null, "tj012", "大黄", "123", "BA", 18000);
employeeDao.insertEmployee(employee);
System.out.println("增加用户成功");
}
}
二 代码重构
通过代码实现对员工表的基础增删改查
1 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Long id;
private String eid;
private String ename;
private String password;
private String job;
private Integer salary;
}
2 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>
<!--类型别名-->
<typeAliases>
<!--一个实体类对应一个别名,映射文件中的resultType属性可以将路径缩写-->
<!--<typeAlias type="cn.tj.mybatis.domain.Employee" alias="employee"></typeAlias>-->
<!--扫描实体类所在的包路径将实体类全部起别名:别名默认是实体类名称 不区分大小写-->
<package name="cn.tj.mybatis.domain"/>
</typeAliases>
<!--配置数据库连接信息-->
<environments default="dev">
<environment id="dev">
<!--配置事务管理模式-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源信息-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="mappers/EmployeeMapper.xml"></mapper>
</mappers>
</configuration>
3 mapper映射文件
<?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="cn.tj.mybatis.mapper.EmployeeMapper">
<!--增加员工:id当前文件中sql标签的唯一标识-->
<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="id">
insert into t_employee(eid,ename,password,job,salary) values(#{eid},#{ename},#{password},#{job},#{salary})
</insert>
<!--修改员工-->
<update id="updateEmployee">
update t_employee set eid=#{eid} ,ename=#{ename} ,password=#{password} ,job=#{job},salary=#{salary} WHERE id=#{id}
</update>
<!--删除员工-->
<delete id="deleteEmployee">
DELETE from t_employee WHERE id=#{id}
</delete>
<!--根据id查询员工:查询必须设置返回类型参数resultType-->
<select id="selectOne" resultType="employee">
SELECT * from t_employee WHERE id=#{id}
</select>
<!--查询所有员工-->
<select id="selectAll" resultType="employee">
SELECT * from t_employee
</select>
<!--模糊查询-->
<select id="selectByName" resultType="employee">
SELECT * from t_employee WHERE ename like "%"#{ename}"%"
</select>
</mapper>
3 db.properties文件(连接数据所需信息)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///web_crud
jdbc.user=root
jdbc.password=root
4 log4j.properties日志文件,可监控mybatis运行(每一条SQL)(需导入log4j jar包)
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.cn.tj.mybatis.mapper=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
5 数据库表
CREATE TABLE `t_employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`eid` varchar(10) NOT NULL,
`ename` varchar(6) NOT NULL,
`job` varchar(10) DEFAULT NULL,
`salary` int(10) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `eid` (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
6 接口
public interface EmployeeDao {
//增加用户
public void insertEmployee(Employee user);
//根据id修改用户
public void updateEmployee(Employee user);
//根据id删除用户
public void deleteEmployee(Long id);
//根据id查询用户
public Employee selectOne(Long id);
//查询所有用户
public List<Employee> selectAll();
//模糊查询
public List<Employee> selectByName(String name);
}
7 实现类
public class EmpoyeeDaoImpl implements EmployeeDao {
@Override
public void insertEmployee(Employee employee) {
try {
//1.加载配置文件信息
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rs);
//2.创建sqlSession
//openSession()默认的时候是需要手动提交事务,如果设置自动提交事务需要参数设置为true
SqlSession sqlSession = factory.openSession(true);
//3.执行增加操作
sqlSession.insert("cn.tj.mybatis.mapper.EmployeeMapper.insertEmployee",employee);
//手动提交事务
// sqlSession.commit();
//4.关闭对象
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void updateEmployee(Employee employee) {
try {
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rs);
SqlSession sqlSession = factory.openSession(true);
sqlSession.update("cn.tj.mybatis.mapper.EmployeeMapper.updateEmployee",employee);
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void deleteEmployee(Long id) {
try {
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rs);
SqlSession sqlSession = factory.openSession(true);
sqlSession.delete("cn.tj.mybatis.mapper.EmployeeMapper.deleteEmployee",id);
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Employee selectOne(Long id) {
try {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = factory.openSession(true);
Employee employee = sqlSession.selectOne("cn.tj.mybatis.mapper.EmployeeMapper.selectOne", id);
return employee;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Employee> selectAll() {
try {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = factory.openSession(true);
List<Employee> employeeList = sqlSession.selectList("cn.tj.mybatis.mapper.EmployeeMapper.selectAll");
return employeeList;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Employee> selectByName(String name) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList("cn.tj.mybatis.mapper.EmployeeMapper.selectByName", name);
}
}
8 工具类
public class MybatisUtil {
private static SqlSessionFactory factory=null;
/*加载配置文件创建工厂对象,只需要加载一次即可*/
static {
try {
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(rs);
} catch (IOException e) {
e.printStackTrace();
}
}
/*加载配置文件创建factory对象*/
public static SqlSession getSqlSession(){
return factory.openSession(true);
}
// 关闭对象
public static void close(SqlSession sqlSession){
if (sqlSession!=null){
sqlSession.commit();
sqlSession.close();
}
}
}
9 测试类
public class EmployeeTest {
private EmployeeDao employeeDao=new EmpoyeeDaoImpl();
/*增加用户测试*/
@Test
public void employee_insert(){
Employee employee=new Employee(null,"tj0118","大黄","123","CTO",18000);
employeeDao.insertEmployee(employee);
System.out.println("用户的id:"+employee.getId());
System.out.println("增加用户成功");
}
/*修改用户*/
@Test
public void employee_update() {
employeeDao.updateEmployee(new Employee(2L,"tj018","大黄","123","CEO",18000));
}
/*删除用户*/
@Test
public void user_delete() {
employeeDao.deleteEmployee(8l);
}
/*根据id查询*/
@Test
public void employee_selectOne() {
Employee employee = employeeDao.selectOne(1l);
System.out.println(employee);
}
/*查询所有*/
@Test
public void employee_selectAll() {
List<Employee> employeeList = employeeDao.selectAll();
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
/*模糊查询*/
@Test
public void employee_selectByname() {
List<Employee> userList =employeeDao.selectByName("大");
for (Employee employee : userList) {
System.out.println(employee);
}
}
}