目录
狂神视频:https://www.bilibili.com/video/BV1NE411Q7Nx
MyBatis
- 什么是MyBatis MyBatis 是一款优秀的持久层框架
- 如何获得
- maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency>
-
Github [Git 代码库]https://github.com/mybatis/mybatis-3/tree/master/src/site
- 为什么需要Mybatis
mybatis是一个半自动化的ORM框架 (Object Relationship Mapping) —>对象关系映射
MyBatis第一个程序
思路流程:搭建环境—>导入Mybatis—->编写代码—->测试
1.搭建环境
CREATE DATABASE `mybatis`;
USE `mybatis`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`name`,`pwd`) values (1,'狂神','123456'),(2,'张三','abcdef'),(3,'李四','987654');
2.创建maven项目,导入MyBatis相关 jar 包
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
测试导入包:
<!--测试junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
3. 编写MyBatis核心配置文件: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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/shusl/dao/userMapper.xml"/>
</mappers>
</configuration>
4. 编写MyBatis工具类:com.shusl.MybatisUtils
package com.shusl.until;
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 java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try {
//使用Mybatis第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
//return sqlSessionFactory.openSession(true);自动提交事务
}
}
5.创建实体类com.shusl.pojo.User
package com.shusl.pojo;
//实体类
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
编写Mapper接口类:com.shusl.dao.UserDao
package com.shusl.dao;
import com.shusl.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
User getUserId(int id);
void deleteById(int id);
void insertUser(User user);
void updateUser(User user);
}
6.编写Mapper.xml配置文件: com.shusl.dao.UserMapper.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.shusl.dao.UserDao">
<select id="getUserList" resultType="com.shusl.pojo.User">
select * from mybatis.user
</select>
<select id="getUserId" parameterType="int" resultType="com.shusl.pojo.User">
select * from mybatis.user where id= #{id}
</select>
<delete id="deleteById" parameterType="int">
delete from mybatis.user where id= #{id}
</delete>
<update id="updateUser" parameterType="com.shusl.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id= #{id}
</update>
<insert id="insertUser" parameterType="com.shusl.pojo.User">
insert mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
</mapper>
7.测试
package com.shusl.dao;
import com.shusl.pojo.User;
import com.shusl.until.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class Test1 {
@Test
public void test(){
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSession
sqlSession.close();
}
@Test
public void byId(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserId(1);
System.out.println(user);
//关闭SqlSession
sqlSession.close();
}
@Test
public void deleteById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.deleteById(6);
sqlSession.commit();
//关闭SqlSession
sqlSession.close();
}
@Test
public void insert(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.insertUser(new User(6,"11","1234"));
sqlSession.commit();
//关闭SqlSession
sqlSession.close();
}
@Test
public void update(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
mapper.updateUser(new User(1,"我我","1234"));
sqlSession.commit();
//关闭SqlSession
sqlSession.close();
}
}
Maven静态资源过滤问题:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
Mybatis的执行过程
方法:打断点看源码
主要知识
Mapper.xml文件解析
namespace
配置文件中namespace中的名称为对应Mapper接口或者Dao接口的完整包名,必须一致!
select
- select语句有很多属性可以详细配置每一条SQL语句
- id
- 命名空间中唯一的标识符
- 接口中的方法名与映射文件中的SQL语句ID 一一对应
- parameterType
- 传入SQL语句的参数类型 。【万能的Map,可以多尝试使用】
- resultType
- SQL语句返回值类型。【完整的类名或者别名】
- id
<select id="getUserList" resultType="com.shusl.pojo.User">
select * from mybatis.user
</select>
insert
<insert id="insertUser" parameterType="com.shusl.pojo.User">
insert mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
update
<update id="updateUser" parameterType="com.shusl.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id= #{id}
</update>
delete
<delete id="deleteById" parameterType="int">
delete from mybatis.user where id= #{id}
</delete>
注意点:增、删、改操作需要提交事务!
结果集映射 ResultMap
为列名指定别名 , 别名和java实体类的属性名一致
<resultMap id="UserMap" type="User">
<!-- id为主键 -->
<id column="id" property="id"/>
<!-- column是数据库表的列名 , property是对应实体类的属性名 -->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="selectUserById" resultMap="UserMap">
select id , name , pwd from user where id = #{id}
</select>
多对一association
多对一:关联-association(多个学生对应一个数学老师)
@Data
public class Student {
private int id;
private String name;
//多个学生可以是同一个老师,即多对一
private Teacher teacher;
}
<resultMap id="StudentTeacher2" type="com.shusl.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="com.shusl.pojo.Teacher">
<result property="name" column="tname"/>
<result property="id" column="tId"/>
</association>
</resultMap>
一对多collection
一对多:集合-collection(一个数学老师对应多个学生)
@Data
public class Teacher {
private int id;
private String name;
//一个老师多个学生
private List<Student> students;
}
<resultMap id="TeacherStudent" type="com.com.shusl.pojo.Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="com.com.shusl.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
配置解析
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!-- 注意元素节点的顺序!顺序不对会报错 -->
日志实现
Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j
- JDK logging
mybatis-config.xml中配置:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Log4j:
- 导入log4j的包
- 配置文件编写
- mybatis-config.xml中setting
- 测试
分页
limit实现分页
#语法
SELECT * FROM table LIMIT stratIndex,pageSize
RowBounds分页(在Java代码层面实现分页)
mybatis分页插件-PageHelper官方文档https://pagehelper.github.io/
动态sql
-
if Where Set
<select id="findList" resultType="ShowUpload"> SELECT <include refid="showUploadColumns"/> FROM dkj_show_upload a <where> <if test="auditStatus != null and auditStatus != ''"> AND a.audit_status = #{auditStatus} </if> <if test="showType != null and showType != ''"> AND a.show_type = #{showType} </if> <if test="showName != null and showName != ''"> AND a.show_name LIKE <if test="dbName == 'oracle'">'%'||#{showName}||'%'</if> <if test="dbName == 'mssql'">'%'+#{showName}+'%'</if> <if test="dbName == 'mysql'">concat('%',#{showName},'%')</if> </if> </where> <choose> <otherwise> ORDER BY a.update_date DESC </otherwise> </choose> </select>
-
SQL片段
<sql id="userColumns"> a.id AS "id", a.name AS "name" </sql> <select id="get" resultType="com.kuang.pojo.User"> SELECT <include refid="userColumns"/> FROM user a WHERE a.id = #{id} </select>
Mybatis缓存
- MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存,
- 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
- 默认是先找二级缓存再找一级缓存
注解开发
- 接口中添加注解
//查询全部用户 @Select("select id,name,pwd password from user") public List<User> getAllUser();
- 在mybatis的核心配置文件中注入
<!--使用class绑定接口--> <mappers> <mapper class="com.kuang.mapper.UserMapper"/> </mappers>
- 测试
@Test public void testGetAllUser() { SqlSession session = MybatisUtils.getSession(); //本质上利用了jvm的动态代理机制 UserMapper mapper = session.getMapper(UserMapper.class); ● List<User> users = mapper.getAllUser(); for (User user : users){ System.out.println(user); } session.close(); }
注解增删改设置自动提交事务
MybatisUtils
//获取SqlSession连接
public static SqlSession getSession(){
return getSession(true); //事务自动提交
}
public static SqlSession getSession(boolean flag){
return sqlSessionFactory.openSession(flag);
}
关于接口的理解
- 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。
- 接口的本身反映了系统设计人员对系统的抽象理解。
- 接口应有两类:
- 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);
- 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);
- 一个体有可能有多个抽象面。抽象体与抽象面是有区别的。
三个面向区别
-
面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法 .
-
面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现 .
-
接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题.更多的体现就是对系统整体的架构
注明:来源从狂神笔记