回顾之前前端访问后端的整个流程:
View ------ >Controller --------> Service ---------> DAO ------> 数据库
View :前端jsp/HTML
Controller:Servlet/SpringMVC
Service :Spring
DAO:jdbc/dbutils/jdbctemplate/mybatis
mybatis实际上就是 DAO层的一个解决方案
jdbc、dbutils、jdbcTemplate、Hibernate以及mybatis的对比:
JDBC:代码非常复杂、速度快
Hibernate:代码精简、缺点(速度慢)
dbutils、jdbcTemplate:不是框架 只是对jdbc的一个简单的封装而已
mybatis:他是属于效率处于JDBC和Hibernate之间
他的代码的复杂度也是趋于 JDBC和Hibernate之间、 代码灵活
iBatis和mybatis之间的关系是什么?
ibatis是以前的叫法 mybatis是现在的叫法
数据库的访问(CRUD)
整合缓存、还可以给类取别名、IBatis还提供了整合Spring的第三方的包
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.6version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.5.10version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.6.1version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12-beta-3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.10version>
dependency>
dependencies>
说明:配置文件的名字可以随意取
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
<environment id="oracle">
<transactionManager type="">transactionManager>
<dataSource type="">dataSource>
environment>
environments>
<mappers>
<mapper resource="UserMapper.xml">mapper>
mappers>
configuration>
<mapper namespace="UserMapper">
<insert id="insert">
insert into t_user (username,password) values ('李四','12344');
insert>
<update id="update">
update t_user set username='王五'
update>
<select id="select" resultType="com.szq.User">
select * from t_user where id=1
select>
<delete id="delete">
delete from t_user where username='王五'
delete>
mapper>
package com.szq;
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.IOException;
import java.io.Reader;
public class Test001 {
/**
* 测试程序
*/
@Test
public void testA() throws IOException {
//1.找到mybatis.xml配置文件
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
//2.创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
//通过工厂构建sqlSession对象
//sqlSession这个对象就是用来操作 数据库的对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//接下来就可以操作数据库了
//添加数据
// sqlSession.insert("UserMapper.insert");
//修改数据
// sqlSession.update("UserMapper.update");
//查询数据
// User o = sqlSession.selectOne("UserMapper.select");
// System.out.println(o);
//删除数据
sqlSession.delete("UserMapper.delete");
sqlSession.commit();//提交
sqlSession.close();//关闭
}
}
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.Reader;
/**
* 帮助类
* mybatis帮助类
*/
public class MyBatisUtils {
//这个类是可以成为成员变量的(没有成员变量,不存在线程安全问题)
private SqlSessionFactory sqlSessionFactory=null;
//保存一个线程局部变量
private ThreadLocal<SqlSession> threadLocal;
{
try {
//需要加载资源
threadLocal = new ThreadLocal();
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsReader);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取操作数据库的对象
*
*/
public SqlSession getSqlSession(){
/**
* 编写访问数据库
* 1:在一个方法体里面 你调用任何多次数据库 我们只是要求 打开一次数据库 以及关闭一次就可以了
* 2;简单的说连接是可以重用的
*/
SqlSession sqlSession = threadLocal.get();
if(null!=sqlSession){//说明不是第一次访问数据库
return sqlSession;
}
//是第一次访问数据库
sqlSession = sqlSessionFactory.openSession();
//方法线程中去
threadLocal.set(sqlSession);
return sqlSession;
}
/**
* 关闭
*/
public void close(){
SqlSession sqlSession = threadLocal.get();
if(null!=sqlSession){
sqlSession.commit();
sqlSession.close();
//将线程中的局部变量置空
threadLocal.remove();
}
}
}
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
<environment id="oracle">
<transactionManager type="">transactionManager>
<dataSource type="">dataSource>
environment>
environments>
<mappers>
<mapper resource="UserMapper1.xml">mapper>
mappers>
configuration>
<mapper namespace="UserMapper">
<insert id="insert" parameterType="map">
insert into t_user(username,password) values (#{username},#{password});
insert>
<update id="update" parameterType="string">
update t_user set username='王五' where username=#{username};
update>
<select id="select" parameterType="int" resultType="com.szq.User">
select * from t_user where id=#{value};
select>
<delete id="delete" parameterType="int">
delete from t_user where id=#{id}
delete>
mapper>
package com.szq.parameter;
import com.szq.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
public class Test002 {
/**
* 测试带参数
*/
@Test
public void testUpdate(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
sqlSession.update("UserMapper.update","张三");
myBatisUtils.close();
}
@Test
public void testSelect(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
Object o = sqlSession.selectOne("UserMapper.select", 2);
System.out.println(o);
myBatisUtils.close();
}
@Test
public void testDelete(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
sqlSession.delete("UserMapper.delete",2);
myBatisUtils.close();
}
}
<insert id="insert" parameterType="map">
insert into t_user(username,password) values (#{username},#{password});
insert>
@Test
public void testInsert(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("username","张三");
objectObjectHashMap.put("password","2222");
sqlSession.insert("UserMapper.insert",objectObjectHashMap);
myBatisUtils.close();
}
<select id="findUserById" resultType="com.szq.User" parameterType="list">
select * from t_user
<if test="array!=null">
where id in
<foreach collection="array" open="(" close=")" separator="," item="id">
#{id}
foreach>
if>
select>
/**
* 传递数组
*/
@Test
public void testFindUserById(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
int arr[]={4,5,6};
List<User> users = sqlSession.selectList("UserMapper.findUserById", arr);
System.out.println(users);
myBatisUtils.close();
}
<select id="findUserById2" resultType="com.szq.User" parameterType="list">
select * from t_user
<if test="list !=null">
where id
<foreach collection="list" open="in (" close=")" separator="," item="id">
#{id}
foreach>
if>
select>
/**
* 传递集合
*/
@Test
public void testFindUserById2(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
ArrayList<Object> objects = new ArrayList<>();
objects.add(4);
objects.add(6);
List<User> users = sqlSession.selectList("UserMapper.findUserById2", objects);
System.out.println(users);
myBatisUtils.close();
}
<select id="select1" parameterType="com.szq.User" resultType="com.szq.User">
select * from t_user t where t.username=#{username} and t.password=#{password};
select>
public void testSelect(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
// User user = new User(1,"张三","123");
User user=new User();
user.setUsername("张三");
user.setPassword("123");
User o = sqlSession.selectOne("UserMapper.select1",user);
System.out.println(o);
myBatisUtils.close();
}
说明:不能一次性传递多个简单的参数
因为后端在接受数据的时候 采用的key是随机的 也就说 可以随便写的 假设你传递了多个简单的参数 那么后端无法区分 这个值是哪一个的
没有办法进行传递 ------ 如果要进行传递 那么你就封装成 map集合 或者 java的类
什么是动态SQL? 在进行查询的时候 会根据前端传递数据的条件 来动态的进行SQL语句的拼接的这种方法 就称为动态SQL
需求:前端随地的给定一串id 要求的是 这一串的id的用户信息全部查询出来 这一串id可以是任意的
id:1,2,3,4 或者3,2,4,5
select * from t_user where id in(不确定)
动态sql解决的问题
<select id="findUserById" resultType="com.szq.User" parameterType="list">
select * from t_user
<if test="array!=null">
where id in
<foreach collection="array" open="(" close=")" separator="," item="id">
#{id}
foreach>
if>
select>
<select id="findUserById2" resultType="com.szq.User" parameterType="list">
select * from t_user
<if test="list !=null">
where id
<foreach collection="list" open="in (" close=")" separator="," item="id">
#{id}
foreach>
if>
select>
<insert id="insert222" parameterType="com.szq.User">
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides="," prefixOverrides="">
<if test="userName != null">
userName,
if>
<if test="password !=null">
password
if>
trim>
<trim prefix="values(" suffix=")" suffixOverrides=",">
<if test="userName != null">
#{userName},
if>
<if test="password !=null">
#{password}
if>
trim>
insert>
<select id="findUserByCondition" parameterType="com.qf.cd.helloworld.User" resultType="com.qf.cd.helloworld.User">
select * from t_user where 1=1
<if test="userName != null">
and userName=#{userName}
if>
<if test="password !=null">
and password=#{password}
if>
select>
<select id="findUserByCondition1" parameterType="com.szq.User" resultType="com.szq.User">
select * from t_user
<include refid="aa">include>
select>
<sql id="aa">
<where>
<if test="userName != null">
and userName=#{userName}
if>
<if test="password !=null">
and password=#{password}
if>
where>
sql>
<select id="findIdByUserName" parameterType="string" resultType="int">
select id from t_user where userName=#{value}
select>
@Test
public void testFindIdByUsername(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
Object id = sqlSession.selectOne("UserMapper.findIdByUserName", "张三");
System.out.println(id);
myBatisUtils.close();
}
<select id="findUserById" parameterType="int" resultType="com.szq.User">
select * from t_user where id=#{value}
select>
@Test
public void testFindUserByUsername(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
Object user = sqlSession.selectOne("UserMapper.findUserById", 6);
System.out.println(user);
myBatisUtils.close();
}
<select id="select2" parameterType="string" resultType="string">
select username from t_user where id in(4,5,6);
select>
/**
* 返回list集合 但是集合中是常见的数据类型
*/
@Test
public void testFindUserById(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<String> str = sqlSession.selectList("UserMapper.select2");
System.out.println(str);
myBatisUtils.close();
}
<select id="select3" resultType="com.szq.User">
select * from t_user ;
select>
/**
* 返回集合,集合是自定义数据类型
*/
@Test
public void testFindAllUser(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<User> users = sqlSession.selectList("UserMapper.select3");
System.out.println(users);
myBatisUtils.close();
}
<select id="findUserAll" resultType="com.szq.parameter1.User">
select id as userId,username as user_Name,password as pass_Word from t_user;
select>
/**
* 通过别名的方式
*/
@Test
public void testFindUserById(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<User> o = sqlSession.selectList("UserMapper.findUserAll");
System.out.println(o);
myBatisUtils.close();
}
<resultMap id="findUserAll2ResultMap" type="com.szq.parameter1.User">
<id property="userId" column="id">id>
<result property="user_Name" column="username">result>
<result property="pass_Word" column="password">result>
<result property="age" column="age">result>
resultMap>
<select id="findUserAll2" resultType="com.szq.parameter1.User" resultMap="findUserAll2ResultMap">
select * from t_user;
select>
/**
* 配置结果集映射
*/
@Test
public void testFindUserById2(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<User> o = sqlSession.selectList("UserMapper.findUserAll2");
System.out.println(o);
myBatisUtils.close();
}
需求:一个用户拥有一个身份证、一个身份证唯一的对应了一个用户
用户与身份证–>是一对一的关系 在查询 用户的时候 ,希望的是能查询出身份证
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
//维护
private IdCard idCard;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class IdCard {
private int id;
private String idNum;
private int userId;
}
<mapper namespace="UserMapper">
<resultMap id="findUserAllResultMap" type="com.szq.oneToone.User">
<id property="id" column="id">id>
<result property="username" column="username">result>
<result property="password" column="password">result>
<result property="age" column="age">result>
<association property="idCard" javaType="com.szq.oneToone.IdCard">
<id property="id" column="cardid">id>
<result property="idNum" column="idNum">result>
<result property="userId" column="userId">result>
association>
resultMap>
<select id="findUserAll" resultMap="findUserAllResultMap">
select * from t_user t1,t_idcard t2 where t1.id=t2.userId
select>
/**
* 一对一映射关系
*/
public class Test001 {
@Test
public void testOneToOne(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<User> o = sqlSession.selectList("UserMapper.findUserAll");
System.out.println(o);
myBatisUtils.close();
}
}
一个部门有多名员工,在查询部门时需求查出部门下的员工
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private int id;
private String deptName;
private String deptDes;
private List<Emp> empList;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {
private int id;
private String empName;
private int gender;
}
<mapper namespace="DeptMapper">
<resultMap id="findDeptResultMap" type="com.szq.oneToMore.Dept">
<id property="id" column="id">id>
<result property="deptName" column="deptName">result>
<result property="deptDes" column="deptDes">result>
<collection property="empList" ofType="com.szq.oneToMore.Emp">
<id property="id" column="empid">id>
<result property="empName" column="empName">result>
<result property="gender" column="gender">result>
collection>
resultMap>
<select id="findDept" resultMap="findDeptResultMap">
select * from t_dept t1,t_emp t2 where t2.deptid=t1.id;
select>
/**
* 一对多映射关系
*/
public class Test001 {
@Test
public void testOneToMore(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<Dept> o = sqlSession.selectList("DeptMapper.findDept");
System.out.println(o);
myBatisUtils.close();
}
}
为什么要整个别名? 因为我们很多时候在写 这个java类型的时候 都写的的全路径
简单的说就是为了解决 传入参数的类型过长 以及 返回参数的类型 过长的问题
mybatis.xml中进行配置
<typeAliases>
<package name="com.szq.one2many">package>
typeAliases>
<settings>
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
settings>
<mappers>
<mapper resource="UserMapper4.xml">mapper>
<mapper resource="IdCardMapper.xml">mapper>
mappers>
<mapper namespace="UserMapper">
<resultMap id="findUserAllResultMap" type="com.szq.oneToone.User">
<id property="id" column="id">id>
<result property="username" column="username">result>
<result property="password" column="password">result>
<result property="age" column="age">result>
<association property="idCard" column="id" javaType="com.szq.oneToone.IdCard" select="IdCardMapper.findIdCard" fetchType="lazy">
association>
resultMap>
<select id="findUserAll" resultMap="findUserAllResultMap">
select * from t_user where id=4;
select>
mapper>
/**
* 测试懒加载
*/
public class Test002 {
@Test
public void test(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List<Object> objects = sqlSession.selectList("UserMapper.findUserAll");
// System.out.println(objects);
myBatisUtils.close();
}
}
缓存:简单的说就是将查询出来的数据 放到一个地方,下一次查询相同的数据的时候不用去查询数据库
直接从缓存里面取数据,这样能够减轻SQL数据库的压力。
一级缓存又叫做session缓存。整个缓存的生命周期由session来进行管理 ,session死了,那么缓存也没有了。
也就是说 一级缓存 实际上存在的范围是 sqlsession的创建完成到sqlsession的关闭之前。
@Test
public void test1(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
User users=sqlSession.selectOne("UserMapper.findUserAll");
User users1=sqlSession.selectOne("UserMapper.findUserAll");
User users3=sqlSession.selectOne("UserMapper.findUserAll");
User users4=sqlSession.selectOne("UserMapper.findUserAll");
User users5=sqlSession.selectOne("UserMapper.findUserAll");
User users6=sqlSession.selectOne("UserMapper.findUserAll");
User users7=sqlSession.selectOne("UserMapper.findUserAll");
//清空一级缓存
sqlSession.clearCache();
sqlSession.commit();
sqlSession.close();
}
查询相同的数据,也就是说sql语句相同,在sqlsession的创建完成到sqlsession的关闭之前,相同的sql语句只会执行一次----一级缓存。一级缓存是不能跨session的 ,现实开发中并没有什么用 ,而且这个缓存的维护 ,也并不需要我们人为的去完成,缓存的使能和销毁都是由session自身去完成的
二级缓存解决了一级缓存的缺点,它能够session进行使用 ,在开发中 一般我们使用的都是二级缓存。
开启二级缓存
<setting name="cacheEnabled" value="true">setting>
导入mybatis的ehcache的支持包
github上下载:https://github.com/mybatis/ehcache-cache/releases
在resource目录下配置ehcache.xml文件
<ehcache
updateCheck="false">
<diskStore path="d:\\mytemp"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
ehcache>
在需要缓存内容的mapper上 使用cache标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache">cache>
* 测试二级缓存
*/
@Test
public void test2(){
MyBatisUtils myBatisUtils = new MyBatisUtils();
SqlSession sqlSession = myBatisUtils.getSqlSession();
List
**测试结果**
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200625204852339.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NzA4NDg1Nw==,size_16,color_FFFFFF,t_70#pic_center)