- MyBatis是一款优秀的持久层框架
- 它支持定制化SQL、存储过程以及高级映射。
- MyBatis避免了几乎所有的JDBCI代码和手动设置参数以及获取结果集。
- MyBatis 可以使用简单的XML或注解来配置和映射原生类型、接口和Java的POJO(Plain old JavaObjects,普通老式Java对象)为数据库中的记录。
MyBatis本是 apache的一个开源项目 iBatis, 2010年这个项目由 apache software foundation迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
数据持久化:jdbc、数据库、io文件保存等
Dao层、Servci层、Controller层
帮程序将数据存入数据库中
方便
传统的JDBC代码太复杂了。简化。框架。自动化。
步骤:
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.9version>
dependency>
public class User {
private String phone;
private String password;
private int id;
@Override
public String toString() {
return "User{" +
"phone='" + phone + '\'' +
", password='" + password + '\'' +
", id=" + id +
'}';
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="findall" resultType="com.wei.domain.User">
select * from users;
select>
mapper>
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/数据库名?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/wei/domain/UserMapper.xml"/>
mappers>
configuration>
public class MyTest01 {
@Test
public void test01() throws IOException {
String config = "sqlMapConfig.xml";
//获得核心配置文件
InputStream is = Resources.getResourceAsStream(config);
//获得工厂对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
// 获得session会话对象,这个就是数据库对象了
SqlSession sqlSession = build.openSession();
//执行操作
//selectList 参数:mapper文件中的namespace + id
List<User> userList = sqlSession.selectList("userMapper.findall");
//打印数据
for(User item : userList){
System.out.println(item);
}
sqlSession.close();
}
}
输出结果:
User{id=1, phone=‘120’, password=‘123456’}
User{id=2, phone=‘987654321’, password=‘123456’}
User{id=3, phone=‘110’, password=‘123456’}
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
向数据库表中插入数据
标签属性:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="findall" resultType="com.wei.domain.User">
select * from users;
select>
<insert id="insertOne" parameterType="com.wei.domain.User">
insert into users value(#{id},#{phone},#{password})
insert>
mapper>
@Test
public void test02() throws IOException {
//创建User对象,用来插入数据库
User user = new User();
user.setId(4);
user.setPhone("147258369");
user.setPassword("123456");
String config = "sqlMapConfig.xml";
//获得核心配置文件
InputStream is = Resources.getResourceAsStream(config);
//获得工厂对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
// 获得session会话对象,这个就是数据库对象了
SqlSession sqlSession = build.openSession();
//执行插入操作,参数:第一个还是namespace + id,第二个是要插入的对象
sqlSession.insert("userMapper.insertOne",user);
sqlSession.commit();
sqlSession.close();
}
这时需要我们手动提交事务,因为Mybatis默认不自动提交事务。
为什么sqlSession中有事务提交?因为它就是个数据库对象啊。
sqlSession.commit()
修改数据库中数据
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="findall" resultType="com.wei.domain.User">
select * from users;
select>
<insert id="insertOne" parameterType="com.wei.domain.User">
insert into users value(#{id},#{phone},#{password})
insert>
<update id="update" parameterType="com.wei.domain.User">
update users set phone=#{phone},password=#{password} where id=#{id}
update>
mapper>
@Test
public void test03() throws IOException {
//创建User对象,修改id为4的数据
User user = new User();
user.setId(4);
user.setPhone("123456789");
user.setPassword("654321");
String config = "sqlMapConfig.xml";
//获得核心配置文件
InputStream is = Resources.getResourceAsStream(config);
//获得工厂对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
// 获得session会话对象,这个就是数据库对象了
SqlSession sqlSession = build.openSession();
//修改id为4的数据
sqlSession.update("userMapper.update",user);
sqlSession.commit();
sqlSession.close();
}
删除数据库中的数据
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="findall" resultType="com.wei.domain.User">
select * from users;
select>
<insert id="insertOne" parameterType="com.wei.domain.User">
insert into users value(#{id},#{phone},#{password})
insert>
<update id="update" parameterType="com.wei.domain.User">
update users set phone=#{phone},password=#{password} where id=#{id}
update>
<delete id="deleteById" parameterType="int">
delete from users where id = #{id}
delete>
mapper>
这里的删除操作是根据id来删除表中的数据段,只有一个参数,#{}中的名字随便起,由于id在数据库是int,所以这里参数类型是int
@Test
public void test04() throws IOException {
String config = "sqlMapConfig.xml";
//获得核心配置文件
InputStream is = Resources.getResourceAsStream(config);
//获得工厂对象
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
// 获得session会话对象,这个就是数据库对象了
SqlSession sqlSession = build.openSession();
//第二个参数:删除id为4的一行数据
sqlSession.update("userMapper.deleteById",4);
sqlSession.commit();
sqlSession.close();
}
生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的并发问题
可以看成数据库连接池
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
因此 SqlSessionFactory的最佳作用域是应用作用域
一般都放在静态代码块中
步骤:
编写实体类
编写UserMapper接口
写实现类去实现Mapper接口
编写Mapper文件
编写核心配置文件
测试
1、实体类
package com.wei.domain;
public class User {
private int id;
private String phone;
private String password;
@Override
public String toString() {
return "User{" +
"id=" + id +
", phone='" + phone + '\'' +
", password='" + password + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.wei.dao;
import com.wei.domain.User;
import java.io.IOException;
import java.util.List;
public interface UserMapper {
// 查找所有用户信息
public List<User> findAll() throws IOException;
}
package com.wei.dao.impl;
import com.wei.dao.UserMapper;
import com.wei.domain.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserMapperImpl implements UserMapper {
@Override
public List<User> findAll() throws IOException {
InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = build.openSession();
List<User> list = sqlSession.selectList("userMapper.findAll");
return list;
}
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="findAll" resultType="com.wei.domain.User">
select * from users;
select>
mapper>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties">properties>
<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>
<mappers>
<mapper resource="com/wei/mapper/UserMapper.xml"/>
mappers>
configuration>
@Test
public void test01() throws IOException {
UserMapper user = new UserMapperImpl();
List<User> all = user.findAll();
for(User item : all){
System.out.println(item);
}
}
输出结果:
User{id=1, phone=‘120’, password=‘123456’}
User{id=2, phone=‘987654321’, password=‘123456’}
User{id=3, phone=‘110’, password=‘123456’}
缺点:
总是要是对象的接口实现,太麻烦了
采用Mybatis的代理开发方式实现DAO层的开发,这种方式是进入企业的主流。
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
@Test
public void test01() throws IOException {
InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = build.openSession();
//使用代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//直接调用方法
List<User> all = mapper.findAll();
for(User item : all){
System.out.println(item);
}
sqlSession.close();
}
sql语句是动态变化的,可以根据条件获取不同的slq语句
主要是where的部分发生变化
动态sql的实现使用的是mybatis提供的标签
对于该标签的执行,当test的值为true时,会将其包含的SQL片断拼接到其所在的SQL语句中。
语法:
sql语句的部分
<mapper namespace="com.wei.dao.UserMapper">
<select id="findByCondition"
parameterType="com.wei.domain.User"
resultType="com.wei.domain.User">
select * from users where 1=1
<if test="id!=0">
and id = #{id}
if>
<if test="phone!=null">
and phone = #{phone}
if>
select>
mapper>
id和phone不传入情况下为了防止出错,设置where 1=1
用来包含多个
的,当多个if中有一个成立的, 会自动增加一个where关键字,并去掉 if 中多余的and , or等
<select id="findByCondition02" resultType="com.wei.domain.User">
select * from student
<where>
<if test="id!=0">
and id = #{id}
if>
<if test="phone!=null">
and phone = #{phone}
if>
where>
select>
用来循环java中的数组,list集合的。主要用在sql的in语句中。
属性:
- collection:表示接口中的方法参数的类型,如果是数组使用array,如果是list集合使用list
- item:自定义的,表示数组和集合成员的变量(随便起名)
- open:循环开始是的字符
- close:循环结束时的字符
- separator:集合成员之间的分隔符
java代码
sqlsession sqlsession = MyBatisutils.getsqlsession();
UserMapper mapper = sqlsession.getMapper(UserMapper.class);
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
List<User> users = mapper.findByIds(list);
for(User item: users){
system.out.println(item);
}
mapper文件
<select id="findByIds" parameteType="list"
resultType="com.wei.domain.User">
select * from users
<where>
<foreach collection="list" item="myid" open="id in (" close=")" separator=",">
#{myid}
foreach>
where>
select>
mysql预编译后结果:Preparing: select * from users where id in ( ?, ? )
标签 用于定义sql 片断,以便其它SQL标签复用。而其它标签使用该SQL片断,需要使用
子标签。该 标签可以定义sQL语句中的任何部分,所以 子标签可以放在动态sQL的任何位置。 步骤:
- 1):先定义
sql语句 / 表名 / 字段等 - 2):使用
引用
<sql id="stusql"> select * from student /sql>
<select id="..." resultType="...">
<include refid="stusql"/>
select>
结果集映射
数据库中名字:id name pwd
实体类中 : id name password
例如:
<resultMap id="UserMap" type="User">
<result column="id" property="id" />
<result column="name" property="name" />
<result column="pwd" property="password" />
resultMap>
<select id="getUserById" resultMap="UserMap">
select * from user where id = #{id}
select>
如果一个数据库操作,出现了异常,我们需要排错。日志就是最好的助手!
SLF4J
LOG4J【掌握】
LOG4j2
JDK_LOGGING
COMMONS_LOGGING
STDOUT_LOGGING【掌握】
NO_LOGGING
在Mybatis核心配置文件中添加下面三行即可开启日志
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/>settings>
#将等级为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/wei.log //将日志输出到当前文件下log/wei.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
1、再要使用log4j中的类中,导入包
static Logger logger = Logger.getLogger(UserDaoTest.class);
3、使用info、debug、error方法
logger.info("info:进入了方法");
logger.debug("debug:进入了方法");
logger.error("error:进入了方法");
大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程
根本原因︰解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;
而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。
-接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。-接口的本身反映了系统设计人员对系统的抽象理解。
-接口应有两类:
-第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);-第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface) ;-一个体有可能有多个抽象面。抽象体与抽象面是有区别的。
-面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法.
-面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现.
-接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题.更多的体现就是对系统整体的架构
// 查询所有用户
@Select("select * from users")
List<User> getList();
<mappers>
<mapper class="com.dao.UserMapper.class"/>
mappers>
本质:反射机制实现
底层:动态代理
接口的方法中,如果参数多于1个,每个基本类型参数前必须加上@pamar
// 查询所有用户
@Select("select * from users where id = #{id},pwd = #{pwd}")
List<User> getList(@Param("id") int id,@Param("pwd") String password);
如果是引用类型,不用写@Param注解,直接写其中的属性名即可
当Dao接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名")mapper文件使用#{自定义参数名}。
例如定义: List
mapper文件: select * from student where name = #{ personName}
接口方法:
List
mapper 文件:
<select id="selectMultiParam" resultType="com.wei.domain.Users">
select * from users
where phone=#{personName} or password=#{password}
select>
使用java对象传递参数,java的属性值就是sql需要的参数值。每一个属性就是一个参数。
语法格式:#{ 对象中的属性名,javaType = java中数据类型名, jdbcType = 数据类型名称 }
javaType, jdbcType 的类型MyBatis可以检测出来,一般不需要设置。常用格式 #{ 对象中的属性名 }
参数位置从0开始,引用参数语法 # arg位置},第一个参数是#{arg0},第二个是#{arg1}
注意: mybatis-3.3版本和之前的版本使用#{0},#{1}方式,从mybatis3.4开始使用#{arg0}方式。
接口方法:
List<User> selectByPhoneAndPwd(String phone,String pwd);
mapper文件
<select id="selectByPhoneAndPwd" resultType="com.wei.domain.Users">
select * from users where phone=#{arg0} or password= #{arg1}
select>
Map集合可以存储多个值,使用Map向mapper文件一次传入多个参数。Map集合使用String的 key,object类型的值存储参数。mapper文件使用# { key }引用参数值。
例如:`
Map<String,String> data = new HashMap<String,String>();
data.put("myphone","111222333");
data.put("mypwd","111222111");
接口方法:
List
mapper文件:
<select id="selectNultiMap" resultType="com.wei.domain.User">
select id,name , email,age from student
where phone=#{myphone} or password=#(mypwd}
select>
# 占位符
,告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql 语句, #{…}代替sql语句的“?”。这样做更安全,更迅速,通常也是首选做法
mapper文件
<select id="selectById" resultType="com.wei.domain.User">
select * from users where id = #{uid}
select>
转为MyBatis 的执行是:
String sql = ” select * from users where id=? ";
PreparedStatement ps = conn.prepareStatement(sql);
uid的值如假设为1005
ps.setInt(1,1005);
解释:
where id = ? 就是 where id = #{uid}
ps.setInt(1,1005) , 1005会替换掉 #{uId}
$ 字符串替换
,告诉mybatis使用$包含的“字符串”替换所在位置。使用Statement把 sql语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。
使用# select * from users where id=#{uid}
#的结果:select* from users where id=?
使用$ select * from users where id=${uid}
$的结果:select * from users where id=1001
string sql="select * from users where id= " + “1001”;
总之:使用$的statement对象执行sql,效率比Preparedstatement低
$ :可以替换表名或者列名,你能确定数据是安全的。可以使用$
# 优点:
- #使用?在sql语句中做站位的,使用Preparedstatement执行sql,效窣高
- #能够避免sql注入,更安全
$ 缺点:
- $ 不使用占位符,是字符串连接方式,使用statement对象执行sql,效率低
- $ 有sql注入的风险,缺乏安全性
- $ :可以替换表名或者列名
resultType结果类型,指sql语句执行完毕后,数据转为的java对象。
处理方式:
注意:resultType 和 resultMap,不能同时使用。
select * from users
对等的jdbc
Resultset rs = executeQuery (" select* from users" );
while (rs.next(){
User user = new User();
User .setId(rs.getInt(“id”));
User.setPhone (rs.getstring ( “phone” ) );
User.setPassword (rs.getstring ( “password” ) );
}//需要有set方法
接口方法:
int countUser();
mapper 文件:
<select id="countStudent" resultType="int">
select count(*) from users
select>
resultType结果类型:1、类型的全限定名 2、类型的别名
在mybatis的主配置文件中配置,使用
标签来定义或者使用 来定义
<typeAliases>
<typeAlias type="" alias=""/>
typeAliases>
<typeAliases>
<package name="com.wei.dao"/>
typeAliases>
sql的查询结果作为Map 的 key 和 value。推荐使用Map
注意:Map作为接口返回值,sql语句的查询结果最多只能有一条记录。大于一条记录是错误。
结果映射,指定列名h额java对象的属性对应关系
可以自定义列值赋值给那个java属性
当列名和属性名不一样时,一定要使用resultMap来指定
接口方法
List<Student> selectMap();
mapper.xml
<select id="selectMap" resultMap="userMap">
select * from users
select>
<resultMap id="userMap" type="com.wei.dao.User">
<id column="id" property="id"/>
<result column="phone" property="phone">
<result column="password" property="password">
resultMap>
1、使用列别名+resultType
2、使用resultMap
1、在java中指定号like的内容,如 %韦%
2、在mapper中拼接like的内容,注意:拼接不要用+
层级关系
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory (对象工厂)
- plugins(插件)
- environments (环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- datasource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
可以通过properties属性来实现引用配置文件
这些属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,亦可通过properties元素的子元素来传递。
<properties resource="db.properties">
<property name="jdbc.username" value="abc"/>
<property name="jdbc.password" value="abc123"/>
properties>
类型别名是为Java类型设置一个短的名字,它只和XML配置有关,存在的意义仅在于用来减少类完全限定名的冗余,例如:
在核心配置文件中为User类起一个别名
<typeAliases>
<typeAlias type="com.wei.domain.User" alias="User"/>
typeAliases>
此时就可以在Mapper文件中使用了,之前的com.wei.domain.User就可以写成user
<select id="findall" resultType="user">
select * from users;
select>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的Java Bean,比如:
扫描实体类的包,它的默认别名就为这个类的类名,首字母小写(其实大写也行)!
<typeAliases>
<package name="com.wei.domain"/>
typeAliases>
此时在Mapper文件中com.wei.domain.User也可以直接写成user
<select id="getList" resultType="user">
select * from users
select>
如果非要再改别名,需要在实体类上写注解
@Alias("myuser")
public class User(){...}
这是MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为。
日志的加载:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING">
settings>
该标签的作用是加载映射的,加载方式有如下几种:
相对于类路径的资源引用
<mappers>
<mapper resource="com/dao/UserMapper.xml"/>
mappers>
<mappers>
<mapper class="com.dao.UserMapper.xml"/>
mappers>
使用classs注意:
<mappers>
<mapper package="com.dao"/>
mappers>
使用package注意:
完全限定资源定位符(URL)
<mappers>
<mapper url:"磁盘中的文件路径"/>
mappers>
Mapper文件
<resultMap id="orderMap" type="com.wei.domain.Order">
<id column="oid" property="id">id>
<result column="ordertime" property="ordertime">result>
<result column="total" property="total">result>
<association property="user" javaType="com.wei.domain.User">
<id column="uid" property="id">id>
<result column="phone" property="phone">result>
<result column="passwrod" property="password">result>
association>
resultMap>
<select id="findByCondition" parameterType="com.wei.domain.User"
resultMap="orderMap">
select * ,o.id oid from orders o, users u where o.uid = u.id
select>
属性是一个对象就用association,如果是集合用constructor
查看用户有哪些订单order
<resultMap id="userMap" type="com.wei.domain.User">
<id column="oid" property="id">id>
<result column="phone" property="phone">result>
<result column="password" property="password">result>
<constructor property="orderList" ofType="com.wei.domain.Order">
<id column="oid" property="id">id>
<result column="ordertime" property="ordertime">result>
<result column="total" property="total">result>
constructor>
resultMap>
<select id="findByCondition" parameterType="com.wei.domain.User" resultMap="userMap">
select * ,o.id oid from orders o, users u where o.uid = u.id
select>
查询数据库耗费资源,一次查询结果暂存在一个可以直接取到的地方,再次查询相同数据时,直接从缓存中取
存在内存中的临时数据。
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
经常查询并且不经常改变的数据。
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
也叫本地缓存(SqlSession),与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
步骤:
步骤:
<setting name="cacheEnable" value="true">
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readonly="true"/>
<select id="getList" resultType="user" useCache="true">
select * from users
select>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用的清除策略有:
LRU
– 最近最少使用:移除最长时间不被使用的对象。FIFO
– 先进先出:按对象进入缓存的顺序来移除它们。SOFT
– 软引用:基于垃圾回收器状态和软引用规则移除对象。WEAK
– 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。默认的清除策略是 LRU。