IBatis的使用
1、IBatis是什么
回顾之前前端访问后端的整个流程:
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是现在的叫法
2、iBatis能做什么
数据库的访问(CRUD)
整合缓存、还可以给类取别名、IBatis还提供了整合Spring的第三方的包
3、IBatis的简单的使用(一)(IBatis的数据不传参的问题)
3.1、导包
<!--导包--><!--下面就是iBatis的相关的包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><!--mysql的驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.5.10</version></dependency><!--日志门面--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.6.1</version></dependency><!-- 单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12-beta-3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version></dependency></dependencies>
3.2编写mybatis.xml配置文件
说明:配置文件的名字可以随意取
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!--这个文件的作用:是对mybatis的全局配置-->
<configuration><!--environments:环境+s,说明可以配置等多个环境这里配置的环境是:数据库的连接信息default:如果配置了多个环境 默认使用哪一个环境--><environments default="mysql"><!--配置一个环境:id:表示的是这个环境的名字逻辑意义上是可以随便写的--><environment id="mysql"><!--配置的是事务的类型 ,默认配置JDBC就可以了 一般情况下使用的就是这个类型--><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><!--这里是可以配置多个环境的 要使用哪一个环境那么就就配置上面的default就可以了 --><environment id="oracle"><transactionManager type=""></transactionManager><dataSource type=""></dataSource></environment></environments><!--在全局配置文件中引入mapper.xml的配置文件--><!--不带参数--><mappers><mapper resource="UserMapper.xml"></mapper></mappers>
</configuration>
3.3、编写UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--nameSpace:命名空间 这个命名空间和其他的命名空间不能重复 一般情况下 实体Mapper逻辑上是可以随便写的 但是实际上要见名之意
-->
<mapper namespace="UserMapper"><!--insert:标签:表示的是 添加数据到数据库id:表示的是方法的名字备注:标签之间 就是写SQL语句的地方--><!--添加数据--><insert id="insert">insert into t_user (username,password) values ('李四','12344');</insert><!--修改数据--><update id="update">update t_user set username='王五'</update><!--查询数据--><!--resultType:表示返回数据的数据类型--><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>
3.3、编写测试代码(CRUD)
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 {/*** 测试程序*/@Testpublic 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();//关闭}
}
4、iBatis的基本的工具类的使用
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();}}
}
5、IBatis的简单使用(二)(IBatis的数据传参的问题)
5.1、传递简单参数问题
5.1.1、编写mybatis.xml配置文件
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!--这个文件的作用:是对mybatis的全局配置-->
<configuration><!--environments:环境+s,说明可以配置等多个环境这里配置的环境是:数据库的连接信息default:如果配置了多个环境 默认使用哪一个环境--><environments default="mysql"><!--配置一个环境:id:表示的是这个环境的名字逻辑意义上是可以随便写的--><environment id="mysql"><!--配置的是事务的类型 ,默认配置JDBC就可以了 一般情况下使用的就是这个类型--><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><!--这里是可以配置多个环境的 要使用哪一个环境那么就就配置上面的default就可以了 --><environment id="oracle"><transactionManager type=""></transactionManager><dataSource type=""></dataSource></environment></environments><!--在全局配置文件中引入mapper.xml的配置文件--><!--带参数--><mappers><mapper resource="UserMapper1.xml"></mapper></mappers>
</configuration>
5.1.2、编写UserMapper1.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--nameSpace:命名空间 这个命名空间和其他的命名空间不能重复 一般情况下 实体Mapper逻辑上是可以随便写的 但是实际上要见名之意
-->
<mapper namespace="UserMapper"><!--传递简单参数 通过id更新数据parameterType:表示的是传进去的参数的数据类型这个数据类型有两种写法1:写Java中数据类型的全路径 java.lang.String java.lang.Integer2:使用mybatis中的数据类型 这个数据类型与 java中的数据类型是一一对应的之前的占位符?在这里写成:#{写对应的key的名字}简单的数据类型 一个字符串 一个int 一个float 没有key 那么这个时候 这个key可以随便写 但是为了见名之意 一般写成value--><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>
5.1.3、编写测试代码(CRUD)
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 {/*** 测试带参数*/@Testpublic void testUpdate(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();sqlSession.update("UserMapper.update","张三");myBatisUtils.close();}@Testpublic void testSelect(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();Object o = sqlSession.selectOne("UserMapper.select", 2);System.out.println(o);myBatisUtils.close();}@Testpublic void testDelete(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();sqlSession.delete("UserMapper.delete",2);myBatisUtils.close();}
}
5.2、传递map集合
5.2.1 、编写xml配置文件
<insert id="insert" parameterType="map">insert into t_user(username,password) values (#{username},#{password});</insert>
5.2.2、编写测试代码
@Testpublic 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();}
5.3 、传递数组
5.3.1 、编写xml配置文件
<!--传递数组--><!--动态sql传递数组的问题通过一连串的id 找用户对象select * from t_user where id in (6,7,8)<if>标签用来做条件判断如果前端传递的是数组类型的数据 那么 这里使用 list来接收遍历数据的时候 那么还是使用 array来做遍历collection:表示的是要遍历的这个集合或者数组open:sql语句的构成 以什么开始close:SQL语句的构成以什么结束separator:遍历出来的数据之间使用什么进行分割item:每一次遍历出来的数据的名字注意:每一次遍历出来的数据 要使用 #{遍历的名字} 去进行获取--><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>
5.3.2、编写测试代码
/*** 传递数组*/@Testpublic 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();}
5.4、传递集合
5.4.1、编写xml配置文件
<!--传递集合--><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>
5.4.2、 编写测试代码
/*** 传递集合*/@Testpublic 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();}
5.5、传递自定义的类的对象
5.5.1、编写xml文件
<!--通过用户名和密码找到用户对象表示的是传递的是 用户对象--><!--传递自定义数据类型User--><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>
5.5.2、编写测试代码
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的类
6、动态SQL的问题
什么是动态SQL? 在进行查询的时候 会根据前端传递数据的条件 来动态的进行SQL语句的拼接的这种方法 就称为动态SQL
需求:前端随地的给定一串id 要求的是 这一串的id的用户信息全部查询出来 这一串id可以是任意的
id:1,2,3,4 或者3,2,4,5
select * from t_user where id in(不确定)
动态sql解决的问题
6.1、传递数组
<!--传递数组--><!--动态sql传递数组的问题通过一连串的id 找用户对象select * from t_user where id in (6,7,8)<if>标签用来做条件判断如果前端传递的是数组类型的数据 那么 这里使用 list来接收遍历数据的时候 那么还是使用 array来做遍历collection:表示的是要遍历的这个集合或者数组open:sql语句的构成 以什么开始close:SQL语句的构成以什么结束separator:遍历出来的数据之间使用什么进行分割item:每一次遍历出来的数据的名字注意:每一次遍历出来的数据 要使用 #{遍历的名字} 去进行获取--><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>
6.2、传递集合
<!--传递集合--><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>
6.3、更新数据
<!--插入数据prefix:前缀 拼接的前缀suffix:拼接的后缀suffixOverrides:这个是去掉结束位置的某一个符号 可以是任意的prefixOverrides:去掉开始的符号 这个符号是任意的--><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>
6.4、动态sql和sql片段
<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标签抽取的sql在任何地方都可以进行调用--><sql id="aa"><where><if test="userName != null">and userName=#{userName}</if><if test="password !=null">and password=#{password}</if></where></sql>
7、iBatis的结果集的返回问题
7.1、返回简单数据
<!--返回简单参数需求:通过用户名 查询用户id--><select id="findIdByUserName" parameterType="string" resultType="int">select id from t_user where userName=#{value}</select>
@Testpublic void testFindIdByUsername(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();Object id = sqlSession.selectOne("UserMapper.findIdByUserName", "张三");System.out.println(id);myBatisUtils.close();}
7.2、返回自定义的类的对象
<!--返回简单参数需求:通过id 查询用户对象--><select id="findUserById" parameterType="int" resultType="com.szq.User">select * from t_user where id=#{value}</select>
@Testpublic void testFindUserByUsername(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();Object user = sqlSession.selectOne("UserMapper.findUserById", 6);System.out.println(user);myBatisUtils.close();}
7.3、返回list集合 但是集合中是常见的数据类型
<!--返回list集合 但是集合中是常见的数据类型-->
<!-- 需求:通过一连串的id 查询一连串的名字-->
<!-- 如果返回集合的数据类型 那么下面的结果集的返回只用写 集合中泛型的数据类型就OK了--><select id="select2" parameterType="string" resultType="string">select username from t_user where id in(4,5,6);</select>
/*** 返回list集合 但是集合中是常见的数据类型*/@Testpublic void testFindUserById(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<String> str = sqlSession.selectList("UserMapper.select2");System.out.println(str);myBatisUtils.close();}
7.4、返回一个集合 集合中的泛型是自定义的类的类型
<!--返回一个集合 集合中的泛型是自定义的类的类型--><select id="select3" resultType="com.szq.User">select * from t_user ;</select>
/*** 返回集合,集合是自定义数据类型*/@Testpublic void testFindAllUser(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<User> users = sqlSession.selectList("UserMapper.select3");System.out.println(users);myBatisUtils.close();}
8、数据库的字段和实体不对应问题
8.1、解决问题之取别名
<!--数据库的字段和实体不对应--><!--解决方法1:使用别名--><select id="findUserAll" resultType="com.szq.parameter1.User"><!--数据库字段 as 实体类字段-->select id as userId,username as user_Name,password as pass_Word from t_user;</select>
/*** 通过别名的方式*/@Testpublic void testFindUserById(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<User> o = sqlSession.selectList("UserMapper.findUserAll");System.out.println(o);myBatisUtils.close();}
8.2、通过结果集映射解决问题
<!--通过结果集映射解决这个问题--><!--配置结果集映射关系--><!--type:是结果集返回的类型--><resultMap id="findUserAll2ResultMap" type="com.szq.parameter1.User"><!--配置主键映射--><!--property:写实体的字段 column:写数据库的字段--><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>
/*** 配置结果集映射*/@Testpublic void testFindUserById2(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<User> o = sqlSession.selectList("UserMapper.findUserAll2");System.out.println(o);myBatisUtils.close();}
9、一对一映射关系
需求:一个用户拥有一个身份证、一个身份证唯一的对应了一个用户
用户与身份证–>是一对一的关系 在查询 用户的时候 ,希望的是能查询出身份证
9.1、用户实体
@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;
}
9.2 、编写方法的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--nameSpace:命名空间 这个命名空间和其他的命名空间不能重复 一般情况下 实体Mapper逻辑上是可以随便写的 但是实际上要见名之意
-->
<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><!--接下来配置一对一的映射关系property:这个实际上就是 java实体中 对象关系的名字javaType:数据类型(全限定名)column:这个是为了将上面的某一个列的内容给映射下来相当于 调用方法的时候要传值select:相当于要调用另外的mapper来实现整个逻辑--><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>
9.3、测试
/*** 一对一映射关系*/
public class Test001 {@Testpublic void testOneToOne(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<User> o = sqlSession.selectList("UserMapper.findUserAll");System.out.println(o);myBatisUtils.close();}
}
10、一对多映射关系
一个部门有多名员工,在查询部门时需求查出部门下的员工
10.1、部门以及员工实体类
@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;
}
10.2、编写xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--nameSpace:命名空间 这个命名空间和其他的命名空间不能重复 一般情况下 实体Mapper逻辑上是可以随便写的 但是实际上要见名之意
-->
<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>
10.3、测试
/*** 一对多映射关系*/
public class Test001 {@Testpublic void testOneToMore(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<Dept> o = sqlSession.selectList("DeptMapper.findDept");System.out.println(o);myBatisUtils.close();}
}
11、取别名的问题
为什么要整个别名? 因为我们很多时候在写 这个java类型的时候 都写的的全路径
简单的说就是为了解决 传入参数的类型过长 以及 返回参数的类型 过长的问题
mybatis.xml中进行配置
<!--取别名--><typeAliases><!--type:是要取别名的这个java类型alias:这个是别名的名字别名一般情况下是取给java实体类的 po dto--><!-- <typeAlias type="com.szq.one2many.Dept" alias="deptbobo"></typeAlias><typeAlias type="com.szq.one2many.Employee" alias="empbobo"></typeAlias>--><!--这个就表示的是给这个包里所有的类都取别名默认的别名的名字是 类名的首写字母小写--><package name="com.szq.one2many"></package></typeAliases>
12、懒加载的问题
12.1、关闭积极的加载、开启懒加载
<!--iBatis本身的设置 -->
<!--mybatis.xml里面设置:注意放置顺序--><settings><!--是否使能延迟的加载 --><setting name="lazyLoadingEnabled" value="true" /><!--关闭那个积极的加载 --><setting name="aggressiveLazyLoading" value="false" /></settings>
12.2、xml配置问题
<!--mybatis.xml里面的mappers配置如下--><mappers><mapper resource="UserMapper4.xml"></mapper><!--懒加载配置如下--><mapper resource="IdCardMapper.xml"></mapper></mappers>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--nameSpace:命名空间 这个命名空间和其他的命名空间不能重复 一般情况下 实体Mapper逻辑上是可以随便写的 但是实际上要见名之意
-->
<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><!--接下来配置一对一的映射关系property:这个实际上就是 java实体中 对象关系的名字javaType:数据类型(全限定名)column:这个是为了将上面的某一个列的内容给映射下来相当于 调用方法的时候要传值select:相当于要调用另外的mapper来实现整个逻辑--><!--懒加载--><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>
12.3、测试代码
/*** 测试懒加载*/
public class Test002 {@Testpublic void test(){MyBatisUtils myBatisUtils = new MyBatisUtils();SqlSession sqlSession = myBatisUtils.getSqlSession();List<Object> objects = sqlSession.selectList("UserMapper.findUserAll");
// System.out.println(objects);myBatisUtils.close();}
}
13、二级缓存的问题
缓存:简单的说就是将查询出来的数据 放到一个地方,下一次查询相同的数据的时候不用去查询数据库
直接从缓存里面取数据,这样能够减轻SQL数据库的压力。
13.1、一级缓存
一级缓存又叫做session缓存。整个缓存的生命周期由session来进行管理 ,session死了,那么缓存也没有了。
也就是说 一级缓存 实际上存在的范围是 sqlsession的创建完成到sqlsession的关闭之前。
@Testpublic 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自身去完成的
13.2、二级缓存
二级缓存解决了一级缓存的缺点,它能够session进行使用 ,在开发中 一般我们使用的都是二级缓存。
开启二级缓存
<!--开启二级缓存--><setting name="cacheEnabled" value="true"></setting>
导入mybatis的ehcache的支持包
github上下载:https://github.com/mybatis/ehcache-cache/releases
在resource目录下配置ehcache.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcacheupdateCheck="false"><!-- 缓存写入文件目录 不需要你引入的 只是配置好就可以 他会默认来找当前的这个位置--><diskStore path="d:\\mytemp"/><!-- 数据过期策略 --><defaultCachemaxElementsInMemory="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<Object> objects1 = sqlSession.selectList("UserMapper.findUserAll");myBatisUtils.close();MyBatisUtils myBatisUtils1 = new MyBatisUtils();SqlSession sqlSession1= myBatisUtils1.getSqlSession();List<Object> objects2 = sqlSession1.selectList("UserMapper.findUserAll");myBatisUtils1.close();MyBatisUtils myBatisUtils2 = new MyBatisUtils();SqlSession sqlSession2 = myBatisUtils2.getSqlSession();List<Object> objects3 = sqlSession2.selectList("UserMapper.findUserAll");myBatisUtils2.close();
}
**测试结果**