【SSM框架 一】Mybatis
文章目录
- 一、Mybatis
- 1、Mybatis简介
- 1.1 什么是Mybatis
- 1.2 获取Mybatis
- 2、第一个Mybatis
- 2.1 搭建环境
- 2.1.1 搭建数据库
- 2.1.2 新建项目
- 2.2 创建一个模块
- 2.2.1 编写核心配置文件
- 2.2.2 编写工具类
- 2.3 编写代码
- 2.3.1 可能会遇到的错误
- 2.3.2 实体类
- 2.3.3 Dao接口
- 2.3.4 接口实现类
- 2.3.5 单元测试
- 3、类作用域
- 4、CURD
- 4.1 select
- 4.2 insert
- 4.3 update
- 4.4 delete
- 4.4 模糊查询
- 5、核心配置文件解析
- 5.1 属性(properties)
- 5.2 设置(settings)
- 5.3 类型别名(typeAliases)
- 5.4 环境配置(environments)
- 5.4.1 事务管理器
- 5.4.2 数据源
- 5.5 映射器(mappers)
- 6、mapper配置文件解析
- 6.1 select标签
- 6.2 insert, update 和 delete
- 6.3 结果映射resultMap
- 6.3.1解决属性名和字段名不一致的问题
- 6.3.2 resultMap标签的属性
- 6.3.3 resultMap标签的子标签
- 6.4 sql片段
- 7、日志
- 7.1 日志工厂
- 7.2 LOG4J
- 8、分页的实现
- 9、使用注解开发
- 9.1 基本使用
- 9.2 CRUD
- 9.3 关于@Param("id")
- 10、lombok(偷懒专用)
- 11、多对一association
- 12、一对多collection
- 13、 动态sql
- 13.1 准备数据
- 13.2 if使用
- 13.3 choose、when、otherwise
- 13.4 trim、where、set
- 13.5 Foreach
- 14、缓存
- 14.1 一级缓存
- 14.2 二级缓存
- 14.3 自定义缓存ehcache
- 15、作业
一、Mybatis
官方文档:https://mybatis.org/mybatis-3/zh/index.html
1、Mybatis简介
1.1 什么是Mybatis
MyBatis 是一款优秀的持久层框架
它支持自定义 SQL、存储过程以及高级映射
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
1.2 获取Mybatis
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version>
</dependency>
2、第一个Mybatis
2.1 搭建环境
2.1.1 搭建数据库
CREATE DATABASE mybatis;
USE mybatis;
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,'张三','123123'),
(2,'李四','111111'),
(3,'王五','121212');
2.1.2 新建项目
创建一个普通的maven项目
删除src目录使其变成一个父工程
导入依赖
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
2.2 创建一个模块
之后我们的项目都是一个个模块
2.2.1 编写核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://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="123456"/></dataSource></environment></environments><mappers><mapper resource="com/daban/dao/UserMapper.xml"/></mappers>
</configuration>
2.2.2 编写工具类
package com.daban.utils;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 {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}public static SqlSession getSqlSession(){return sqlSessionFactory.openSession();}
}
2.3 编写代码
2.3.1 可能会遇到的错误
org.apache.ibatis.binding.BindingException: Type interface com.daban.dao.UserDao is not known to the MapperRegistry.
意思是没有在mybatis的配置文件中注册mapper,需要在配置文件中添加注册
<mappers><mapper resource="com/daban/dao/UserMapper.xml"/> </mappers>
org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/daban/dao/UserMapper.xml
不能找到mapper.xml文件,因为在构建的时候没有导出该文件,如下代码到pom中可以解决
<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>
- org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 14; 1 字节的 UTF-8 序列的字节 1 无效。
是因为xml文件中的注释使用了中文,去掉即可,或者将encoding="UTF-8"改为encoding=“UTF8”(原因不明)
2.3.2 实体类
package com.daban.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;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}
}
2.3.3 Dao接口
package com.daban.dao;import com.daban.pojo.User;import java.util.List;public interface UserDao {List<User> getUserList();
}
2.3.4 接口实现类
(由之前的实现类转变成一个Mapper配置文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace绑定一个接口,相当于实现一接口-->
<mapper namespace="com.daban.dao.UserDao">
<!-- id就是接口中的方法名字-->
<!-- resultType返回类型要写类型的全名--><select id="getUserList" resultType="com.daban.pojo.User">select * from mybatis</select>
</mapper>
2.3.5 单元测试
package com.daban.dao;import com.daban.pojo.User;
import com.daban.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class UserMapperTest {@Testpublic void test(){//获取sqlSessionSqlSession sqlSession = MybatisUtils.getSqlSession();//得到UserDao的MapperUserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.getUserList();for (User user: userList) {System.out.println(user);}sqlSession.close();}
}
3、类作用域
类 | 作用域 | 备注 |
---|---|---|
SqlSessionFactoryBuilder | 最佳作用域是方法作用域(也就是局部方法变量) | |
SqlSessionFactory | 最佳作用域是应用作用域 | 想象为数据库连接池 |
SqlSession | 最佳的作用域是请求或方法作用域 | 连接到连接池的一个请求,用完关闭 |
4、CURD
记住,在增删改的时候需要提交事务才可以生效sqlSession.commit();
4.1 select
1、编写接口
//通过id查询用户
User getUserById(int id);
2、编写对应mapper中的sql语句
<select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >select * from mybatis.user where id = #{id}
</select>
3、测试
public void getUserById(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User userById = mapper.getUserById(1);System.out.println(userById);sqlSession.close();
}
4.2 insert
1、编写接口
//增加一个用户
void addUser(User user);
2、编写对应mapper中的sql语句
<insert id="addUser" parameterType="com.daban.pojo.User">insert into mybatis.user values(#{id},#{name},#{pwd})
</insert>
3、测试
public void addUser(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.addUser(new User(5,"嫦娥","333333"));//增删改必须要提交事务sqlSession.commit();sqlSession.close();
}
4.3 update
1、编写接口
//修改一个用户
void updateUser(User user);
2、编写对应mapper中的sql语句
<update id="updateUser" parameterType="com.daban.pojo.User">update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
</update>
3、测试
public void updateUser(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.updateUser(new User(5,"大圣","888888"));sqlSession.commit();sqlSession.close();
}
4.4 delete
1、编写接口
//删除一个用户
void deleteUser(User user);
2、编写对应mapper中的sql语句
<delete id="deleteUser" parameterType="com.daban.pojo.User">delete from mybatis.user where id=#{id}
</delete>
3、测试
public void deleteUser(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);mapper.deleteUser(new User(5));sqlSession.commit();sqlSession.close();
}
4.4 模糊查询
1、编写接口
//通过name查询用户
List<User> getUserByName(String name);
2、编写对应mapper中的sql语句
<select id="getUserByName" resultType="com.daban.pojo.User" parameterType="string" >select * from mybatis.user where name like #{name}
</select>
3、测试
public void getUserByName(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.getUserByName("%张%");for (User user: userList) {System.out.println(user);}sqlSession.close();
}
5、核心配置文件解析
首先配置文件中标签是有顺序的,写反会报错
properties>settings>typeAliases>typeHandlers>objectFactory>objectWrapperFactory>reflectorFactory>plugins>environments>databaseIdProvider>mappers
5.1 属性(properties)
引入一个配置文件,使mybatis的核心配置文件可以引用该配置文件里面的参数
<properties resource="config.properties"><!--标签里也可以有属性,和外部文件里面写的属性,效果一样,只是有一个优先级--><property name="username" value="root"/><property name="password" value="123456"/>
</properties>
获取值的方式
<environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment>
</environments>
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
5.2 设置(settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为
官网查找https://mybatis.org/mybatis-3/zh/configuration.html
5.3 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写
<typeAliases><typeAlias alias="user" type="com.daban.pojo.User"/>
</typeAliases>
可以通过包来起别名,包下的所有实体类,都可以使用类名的首字母小写来代替全名,给实体类加注解,可以diy
<typeAliases><package name="com.daban.pojo"/>
</typeAliases>
5.4 环境配置(environments)
<environments default="development">默认使用的环境<environment id="development">定义的环境标识,可随意标识,保证默认的环境 ID 要匹配其中一个环境 ID<transactionManager type="JDBC"/>事务管理器配置<dataSource type="POOLED">数据源配置<property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment>
</environments>
5.4.1 事务管理器
在 MyBatis 中有两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”)
如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置
5.4.2 数据源
有三种内建的数据源类型(也就是 type=“[UNPOOLED|POOLED|JNDI]”),
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择
POOLED(常用)– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间
JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用
5.5 映射器(mappers)
告诉 MyBatis 到哪里去找到sql语句
方式一、【推荐使用】
<!-- 使用相对于类路径的资源引用 -->
<mappers><mapper resource="com/daban/dao/UserMapper.xml"/>
</mappers>
方式二、
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers><mapper class="com.daban.dao.UserMapper"/>
</mappers>
注意点:
接口和他的mapper配置文件必须同名
接口和他的mapper配置文件必须在同一个包下
方式三、
<!-- 将包内的映射器接口全部注册为映射器 -->
<mappers><package name="com.daban.dao"/>
</mappers>
注意点:
接口和他的mapper配置文件必须同名
接口和他的mapper配置文件必须在同一个包下
方式四、【不建议使用】
<!-- 使用完全限定资源定位符(URL) -->
<mappers><mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
6、mapper配置文件解析
6.1 select标签
<select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >select * from mybatis.user where id = #{id}
</select>
select元素的属性
<selectid="selectPerson" dao接口中的方法名字parameterType="int" 参数的类全限定名或别名。这个属性是可选的parameterMap="deprecated" 废弃了resultType="hashmap" 返回结果的类全限定名或别名,如果是集合,写集合泛型resultMap="personResultMap" 对实体类和字段名字不一样时的处理,结果映射flushCache="false" 每次sql执行,都刷新清除一二级缓存useCache="true" 开启二级缓存timeout="10" 在抛出异常之前,驱动程序等待数据库返回请求结果的秒数fetchSize="256" 尝试让驱动程序每次批量返回的结果行数等于这个设置值statementType="PREPARED" 可选 STATEMENT,PREPARED 或 CALLABLEresultSetType="FORWARD_ONLY">
6.2 insert, update 和 delete
<insert id="insertAuthor">insert into Author (id,username,password,email,bio)values (#{id},#{username},#{password},#{email},#{bio})
</insert><update id="updateAuthor">update Author setusername = #{username},password = #{password},email = #{email},bio = #{bio}where id = #{id}
</update><delete id="deleteAuthor">delete from Author where id = #{id}
</delete>
属性
<insertkeyProperty="" 设置自增主键的字段keyColumn=""useGeneratedKeys="" 开启自增主键timeout="20">
6.3 结果映射resultMap
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了
6.3.1解决属性名和字段名不一致的问题
方式一、起别名
<select id="getUserById" resultType="com.daban.pojo.User" parameterType="int" >select user_id as id,user_name,user_pwd from mybatis.user where id = #{id}
</select>
方式二、使用resultMap
<resultMap id="userResultMap" type="User"><id property="id" column="user_id" /><result property="username" column="user_name"/><result property="password" column="user_password"/>
</resultMap>
<select id="getUserById" resultMap="userResultMap" parameterType="int" >select from mybatis.user where id = #{id}
</select>
6.3.2 resultMap标签的属性
标签 | 解释 | 备注 |
---|---|---|
id | 当前命名空间中的一个唯一标识,用于标识一个结果映射。 | 和select标签中的 resultMap绑定 |
type | 类的完全限定名, 或者一个类型别名。 | 不用结果集映射时,select标签中的resultType的值 |
autoMapping | 如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射 |
6.3.3 resultMap标签的子标签
标签 | 解释 | 备注 |
---|---|---|
constructor | 用于在实例化类时,注入结果到构造方法中 | |
id | 标记出作为 ID 的结果可以帮助提高整体性能 | |
result | 注入到字段或 JavaBean 属性的普通结果 | |
association | 个复杂类型的关联;许多结果将包装成这种类型 | 相当于对象 |
collection | 一个复杂类型的集合 | 相对于集合 |
discriminator | 使用结果值来决定使用哪个 |
6.4 sql片段
这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<include refid="userColumns"><property name="alias" value="t1"/></include>
7、日志
7.1 日志工厂
<settings><!--标准的日志工厂实现--><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
设置里设置logImpl的值:
SLF4J
LOG4J(3.5.9 起废弃)
LOG4J2
JDK_LOGGING
COMMONS_LOGGING
STDOUT_LOGGING
NO_LOGGING
7.2 LOG4J
1、先导包
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
2、配置log4j的配置文件
resources下新建一个log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/logFile.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3、使用
import org.apache.log4j.Logger;
Logger logger = Logger.getLogger(UserTest.class);//获得logger对象,参数为当前类的class
logger.info("我是info");
logger.debug("我是调试信息");
logger.error("我是error");
8、分页的实现
原理就是使用map来传递limit的参数
1、接口方法
List<User> getUserListLimit(Map<String,Object> map);
2、mapper配置文件
<mapper namespace="com.daban.dao.UserMapper"><resultMap id="userMap" type="user"><result property="password" column="pwd"/></resultMap><select id="getUserListLimit" resultMap="userMap" parameterType="map">select * from mybatis.user limit #{startIndex},#{pageSize}</select>
</mapper>
3、测试
public void test(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String, Object> map = new HashMap<>();map.put("startIndex",2);map.put("pageSize",3);List<User> userList = mapper.getUserListLimit(map);for (User user : userList) {System.out.println(user);}sqlSession.close();
}
9、使用注解开发
9.1 基本使用
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句
1、删除接口的mapper文件
2、接口中使用注解
@Select("select * from mybatis.user")
List<User> getUserList();
3、mybatis核心配置文件中使用类绑定
<mappers><mapper class="com.daban.dao.UserMapper"/>
</mappers>
这样会发现无法进行结果集映射,这是使用注解的弊端
9.2 CRUD
SqlSession sqlSession = factory.openSession(true);//参数为是否自动提交,设置true后,不需要手动提交
//但是在使用注解时,会自动提交
public interface UserMapper {//查询所有@Select("select * from mybatis.user")List<User> getUserList();//查询,一个参数可以省略@Param@Select("select * from mybatis.user where id = #{id}")User getUserById(int id);//查询俩个参数,不能省略@Param@Select("select * from mybatis.user where id = #{id} and name = #{name}")User getUserByIdAndName(@Param("id") int id,@Param("name") String name);//增加@Select("insert into mybatis.user values(#{id},#{name},#{password})")void addUser(User user);//修改@Select("update mybatis.user set name=#{name},pwd=#{password} where id = #{id} ")void updateUser(User user);//删除@Select("delete from mybatis.user where id = #{id}")void deleteUser(User user);
}
9.3 关于@Param(“id”)
- 基本参数类型和String类型需要加上
- 引用类型不需要加
- 如果只有一个基本类型,可以忽略,建议加上
10、lombok(偷懒专用)
1、idea中的plugin中安装lombok
2、导入lombok的jar包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope>
</dependency>
3、使用
在实体类上加注解就行
@Getter//get方法
@Setter//set方法
@ToString//ToString方法
@EqualsAndHashCode//EqualsAndHashCode方法
@NoArgsConstructor//无参构造方法
@Data//以上都创建了@AllArgsConstructor//所有参数构造方法
11、多对一association
其实就是解决属性名和字段名不一致的问题,因为联表查询把其他表的字段放在了该表里,名称类型可能不一致
准备sql
CREATE TABLE teacher(`id` INT(20) NOT NULL,`name` VARCHAR(30) DEFAULT NULL,PRIMARY KEY (`id`))ENGINE INNODB DEFAULT CHARSET=utf8;INSERT INTO teacher(`id`,`name`) VALUES(1,"张老师");CREATE TABLE student(`id` INT(20) NOT NULL,NAME VARCHAR(30) DEFAULT NULL,`tid` INT(10) DEFAULT NULL,PRIMARY KEY (`id`),FOREIGN KEY (`tid`) REFERENCES `teacher`(`id`)
)ENGINE INNODB DEFAULT CHARSET = utf8;INSERT INTO student(`id`,`name`,`tid`) VALUES(1,"小明",1);
INSERT INTO student(`id`,`name`,`tid`) VALUES(2,"小张",1);
INSERT INTO student(`id`,`name`,`tid`) VALUES(3,"小李",1);
INSERT INTO student(`id`,`name`,`tid`) VALUES(4,"小王",1);
INSERT INTO student(`id`,`name`,`tid`) VALUES(5,"小红",1);
实体类
@Data
public class Student {private int id;private String name;private Teacher teacher;
}
@Data
public class Teacher {private int id;private String name;
}
mapper文件
<mapper namespace="com.daban.dao.StudentMapper"><!--方式一、联表查询,嵌套方式--><resultMap id="getStudentListMap1" type="com.daban.pojo.Student"><result property="id" column="s_id"/><result property="name" column="s_name"/><association property="teacher" javaType="com.daban.pojo.Teacher" ><result property="name" column="t_name"/><result property="id" column="t_id"/></association></resultMap><select id="getStudentList1" resultMap="getStudentListMap1">select s.id as s_id,s.name as s_name,t.name as t_name,t.id as t_idfrom mybatis.student s , mybatis.teacher twhere t.id = s.tid</select><!--方式二、联表查询,子查询方式--><resultMap id="getStudentListMap2" type="com.daban.pojo.Student"><result property="id" column="id"/><result property="name" column="name"/><association property="teacher" column="tid" javaType="com.daban.pojo.Teacher"select="getTeacherList"/></resultMap><select id="getStudentList2" resultMap="getStudentListMap2">select * from mybatis.student</select><select id="getTeacherList" resultType="com.daban.pojo.Teacher">select * from mybatis.teacher where id = #{id}</select></mapper>
12、一对多collection
其实就是解决属性名和字段名不一致的问题,因为联表查询把其他表的字段放在了该表里,名称类型可能不一致
实体类
@Data
public class Teacher {private int id;private String name;private List<Student> student;
}
@Data
public class Student {private int id;private String name;private int tid;
}
mapper文件
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.daban.dao.TeacherMapper"><!--方式一、联表查询,嵌套方式--><resultMap id="getTeacherListMap1" type="com.daban.pojo.Teacher"><result property="id" column="t_id"/><result property="name" column="t_name"/><collection property="student" column="t_id" ofType="com.daban.pojo.Student"><result property="id" column="s_id"/><result property="name" column="s_name"/><result property="tid" column="s_tid"/></collection></resultMap><select id="getTeacherList1" resultMap="getTeacherListMap1">select t.id as t_id,t.name as t_name,s.id as s_id,s.name as s_name,s.tid as s_tidfrom mybatis.teacher t,mybatis.student s where s.tid=t.id;</select><!--方式二、联表查询,子查询方式--><resultMap id="getTeacherListMap2" type="com.daban.pojo.Teacher"><result property="id" column="id"/><result property="name" column="name"/><collection property="student" column="id" ofType="com.daban.pojo.Student"javaType="ArrayList" select="getStudentList"/></resultMap><select id="getTeacherList2" resultMap="getTeacherListMap2">select * from mybatis.teacher</select><select id="getStudentList" resultType="com.daban.pojo.Student">select * from mybatis.student where tid = #{tid}</select>
</mapper>
13、 动态sql
13.1 准备数据
<settings><setting name="logImpl" value="STDOUT_LOGGING"/>开启数据库下划线命名和实体类属性驼峰命名的对应<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
根据不同的条件生成不同的sql语句
sql准备
CREATE TABLE blog(`id` INT(50) NOT NULL,`title` VARCHAR(100) NOT NULL,`author` VARCHAR(30) NOT NULL,`create_time` DATETIME NOT NULL,`views` INT(30) NOT NULL)ENGINE INNODB DEFAULT CHARSET=utf8;
表中插入数据:
<insert id="addBlog" parameterType="blog">insert into mybatis.blog(`id`,`title`,`author`,`create_time`,`views`)values (#{id},#{title},#{author},#{createTime},#{views});
</insert>
public void addBlog(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);mapper.addBlog(new Blog(IDUtils.getID(),"庆祝二十大顺利召开","中央视频",new Date(),9999));mapper.addBlog(new Blog(IDUtils.getID(),"中纪委公布查处中央委员人数","中央视频",new Date(),500));mapper.addBlog(new Blog(IDUtils.getID(),"小学生捡到“十万元”组团交派出所","华商报",new Date(),2344));mapper.addBlog(new Blog(IDUtils.getID(),"浪漫同框!中国空间站飞越北京上空","华商报",new Date(),555));mapper.addBlog(new Blog(IDUtils.getID(),"中国要搞自给自足?发改委:误解","四川观察",new Date(),1234));sqlSession.commit();sqlSession.close();
}
13.2 if使用
注意map中的key要和if里面的title对应上(名称一致)
当sql语句中包含小于号时,不被识别。只能使用大于号,解决办法,前后颠倒要比较的值
<select id="queryBlogIf" resultType="blog" parameterType="map">select * from mybatis.blog where 1=1<if test="title!=null">and title like #{title}</if><if test="views!=null">and #{views} > views</if>
</select>
public void queryBlogIf(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);Map<String, Object> map = new HashMap<>();map.put("title","%中%");map.put("views",1000);List<Blog> blogs = mapper.queryBlogIf(map);for (Blog blog : blogs) {System.out.println(blog);}
}
13.3 choose、when、otherwise
类似与java的switch case语句:第一个满足条件后面都不执行了,都不满足执行otherwise
<select id="queryBlogChoose" resultType="blog" parameterType="map">select * from mybatis.blog where 1=1<choose><when test="title!=null">and title like #{title}</when><when test="author!=null">and #{author} = author</when><otherwise>and #{views} > views</otherwise></choose>
</select>
public void queryBlogChoose(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);Map<String, Object> map = new HashMap<>();
// map.put("title","%中%");map.put("author","华商报");map.put("views",1000);List<Blog> blogs = mapper.queryBlogChoose(map);for (Blog blog : blogs) {System.out.println(blog);}}
13.4 trim、where、set
where 元素自动插入 “WHERE” 。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
where和set都可以使用trim实现,只不过,trim更可以自定义
13.5 Foreach
<select id="queryBlogForeach" parameterType="map" resultType="blog">select * from mybatis.blog<where><foreach collection="viewsList" item="view" open="(" separator="or" close=")">views = #{view}</foreach></where></select>
public void queryBlogForeach(){SqlSession sqlSession = MybatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);Map<String, Object> map = new HashMap<>();ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(9999);arrayList.add(2344);map.put("viewsList",arrayList);List<Blog> blogs = mapper.queryBlogForeach(map);for (Blog blog : blogs) {System.out.println(blog);}
}
14、缓存
查询的结果放在内存中,我们再次查询相同数据时,就可以走缓存,从而减少数据库的连接,减低资源损耗
经常查询且不经常改变的数据,可以使用缓存
创建实体类时,要实现序列化,这样对象才能被缓存,不然报错
mybatis默认两级缓存:
- 一级缓存:默认开启,sqlsession级别的缓存
- 二级缓存:需要手动开启,namespace级别的缓存
14.1 一级缓存
缓存失效的情况:
1、查询不同的数据
2、增删改操作,可能会改变原来的数据,所以必定会刷新缓存
3、查询不同的mapper.xml
4、手动清理缓存(sqlSession.clearCache();)
14.2 二级缓存
打开方式:在mapper文件中加入标签即可开启二级缓存
会话关闭时,就会将一级缓存中的数据保存到二级缓存,新的会话查询就会从二级缓存查询
14.3 自定义缓存ehcache
java的分布式缓存
1、先导包
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.2</version>
</dependency>
2、mapper文件中设置
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
3、增加配置文件ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><!-- 磁盘缓存位置 --><diskStore path="java.io.tmpdir/ehcache"/><!-- 默认缓存 --> <!-- name:缓存名称。 maxElementsInMemory:缓存最大个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。 diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 maxElementsOnDisk:硬盘最大缓存个数。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 --><defaultCachemaxElementsInMemory="10"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="3600"overflowToDisk="true"memoryStoreEvictionPolicy="LRU"/><!-- deptrole缓存 --><cache name="deptrole"maxElementsInMemory="10"eternal="false"timeToIdleSeconds="86400"timeToLiveSeconds="86400"overflowToDisk="true"memoryStoreEvictionPolicy="LRU"/></ehcache>
15、作业
用mybatis重新写smbms项目
【SSM框架 一】Mybatis相关推荐
- JavaWeb学习之路——SSM框架之Mybatis(三)
数据库配置和相关类创建看上篇:JavaWeb学习之路--SSM框架之Mybatis(二) https://blog.csdn.net/kuishao1314aa/article/details/832 ...
- SSM框架——使用MyBatis Generator自动创建代码
SSM框架--使用MyBatis Generator自动创建代码 这是通过命令行, 不用ide插件. 若在IDEA中通过插件generator, 还可以参考另一篇: IDEA搭建Spring+Spri ...
- SSM框架-使用MyBatis Generator自动创建代码
参考:http://blog.csdn.net/zhshulin/article/details/23912615 SSM搭建的时候用到MyBatis的代码自动生成的功能,由于MyBatis属于一种半 ...
- JavaWeb学习之路——SSM框架之Mybatis(二)
1.简介: 框架: 是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架.前者是从应用方面而后者是从目的方面给出的定义.它是一个半 ...
- SSM框架使用mybatis反向生成实体类、dao和映射文件
2.1反向生成配置文件generatorConfig.xml 文件命名generatorConfig.xml为放在resources里 <generatorConfiguration> & ...
- SSM框架学习----Mybatis(2)
Mybatis框架学习--中 Mybatis框架学习----(2) 1. Mybatis的自定义分析 1. 第一步 2. 第二步 3. 第三步 4. 第四步 5. 第五步 2. Mybatis实现CR ...
- SSM框架-实现Mybatis分页功能-foreknow_cms
##分页处理 分页 1.前台分页 2.数据库(后台)分页 3.存储过程 Orade (Rownum) Mysql(limit) sqlservier(Top N) 第一步 : 要在mybatis 核心 ...
- SSM框架专题-MyBatis框架老杜版从零入门笔记(下)
七.MyBatis参数处理 7.1 单个简单参数 parameterType表示传入参数的类型,官方文档有很多别名可以参考 <insert id="insertStu" pa ...
- SSM框架之Mybatis同时传入多个对象及普通参数
当传入多个文件时,mapper接口文件的方法参数要使用@param("xx")注释. 例子: mapper: //Student是对象,age是String类型. int getP ...
- mysql如何导入myeclisp中_MyEclipse搭建SSM框架(Spring+MyBatis+SpringMVC)
如何使用CSS绘制一个响应式的矩形 背景: 最近因为需要用到绘制类似九宫格的需求,所以研究了一下响应式矩形的实现方案. 有如下几种方案: 使用js来设置元素的高度 使用vw单位 div {width ...
最新文章
- RandomAccessFile r rw rws rwd之间的区别
- Linux如何让命令提示符显示完整的路径
- Failed to set NvVAD endpoint as default Audio endpoint [0]
- mysql行锁和表锁
- Template methed
- C语言经典算法 1-10
- PHP的uniqid
- 在jsp页面实现保存登录用户名和密码
- 评奖.婚礼及“形而上”
- 二分类预测用的几个预测结果精确度计算方法
- 如何理解自然语言处理中的注意力机制? | 技术头条
- 《Java8实战》读书笔记
- springboot集成quartz
- 聊一聊数学中的基本定理(二)——算术基本定理的价值
- imagej对像素进行操作
- [数值计算-11]:多元函数求最小值 - 偏导数与梯度下降法Python法代码示例
- win10 ISO文件下载
- zabbix企业应用之自动语音报警平台
- 电脑用cmd命令将手机中的文件导入电脑中
- 【英语论文】英汉委婉语的文化价值和民族特质比较(节选)