框架 MYbatis
MyBatis简介:
MyaBtis 本来是apache的一个开源项目IBatis,2010年这个项目迁移到了 google Code 并改名为MyBatis 是一个Java的持久层框架。
优点:
1、与JDBC相比减少了50%以上的代码量
2、最简单的持久层框架,小巧
3、SQL代码与程序代码彻底分离(可重用)
4、提供XML标签,支持编写动态的SQL语句
5、提供映射标签,支持对象与数据库的ORM字段映射
缺点:
1、SQL语句的编写工作量比较大,对开发人员有一定的要求
2、数据库移植性差
MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案,适用于性能要求较高 或者 需求较多变的互联网项目
为什么使用MyBatis?
在传统的JDBC中,我们除了需要自己提供SQL之外,还必须操作Connection、Statment、ResultSet、为了访问不同的表,不同字段的数据,我们需要很多的雷同代码,
而我们使用了MyBatis之后 ,只需要提供sql语句就好了,好处:我们的“关注点可以集中在sql语句上”关注到增删查改这些操作层面上 并且MyBatis支持简单xml或注解配置和映射原生信息,将接口 和Java的POJO(Plain Old Java Objects普通的Java对象) 映射成数据库中的记录
mapper接口是怎么映射成sql语句的
使用xml来进行Mybatis的配置,包括Mybatis的核心配置和SQL映射配置(注解配置)。Xml本身只不过是一个元素的载体最终起作用的是MyBatis的核心类:
1、SqlSessionFactoryBuilder用来创建SqlSessionFactory的实例(对象)之后就没有用了,其生命周期知识在初识化时有做用
2、SqlSessionFactory,是MyBatis的基础类,用来创建会话(SqlSession)的实例(对象),其生命周期与整个系统的生命周期相同,在系统运行的任何时候都可以使用SqlSessionFactory来查询当前对数据库配置信息等。
3、SqlSession 真正和数据库之间的会话,线程不安全,其生命周期和其他线程相同
4、各种Mapper,承载了实际的业务逻辑,生命周期比较短,由SqlSession创建
MyBatis 本身就是一个简单的ORM框架,提供了SQL语句到方法、关系型数据表到对象的映射。实际使用中与开发相关的两个东西:
1、MyBatis 的核心配置
缓存、数据源、日志等关系到MyBatis的本身行为一些配置
2、mapper接口的映射
针对具体的业务逻辑的SQL映射
属性 | 描述 |
---|---|
id | 命名空间的标识符 》 接口名称 |
parameterType | 参数的类的全名或者别名 可选 默认为空 |
parameterMap | |
resultType | 返回结果的类型的全名或者 别名 。如果结果是集合 此类型表示的是集合的成员类型 |
resultMap | 使用resultMap来映射结果集,resultType和resultMap 只能选择一个用 |
flushCache | 如果为true,每次调用一级缓存和二级缓存都会回写,select中默认为false |
useCache | 如果为true 结果将在二级缓存中缓存 select中默认为true |
timeout | 设置超时,若超时抛出异常 |
更新语句(insert update delete)
属性 | 描述 |
---|---|
useGeneratedKeys | 将使用JDBC的getGeneratedKeys方法获取主键值 默认为false |
keyProperty | 主键,MyBatis会将生成的主键赋给这个列 |
keyColumn | 特定数据库需要使用 |
association | 一对一的单向关联 查询的结果中包含有其他的对象 比如 学生集合中每一个学生的年级对象 |
collection | 一对多的关联 查询结果中包含有其他的集合 比如学生集合中包含了开始成绩 集合 |
maven的配置
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven是一个项目管理工具,它包含了一个
项目对象模型 (Project Object Model),
一组标准集合,
一个项目生命周期(Project Lifecycle),
一个依赖管理系统(Dependency Management System)
Apache Maven 是一个软件项目管理工具。项目对象模型 (Project Object Model)的概念
Maven可以用来管理项目的依赖、编译、文档等信息
使用Maven管理项目时,项目的依赖的jar将不在包含在项目中,而是集中保存在本地
目录:C:\Users\Administrator \ .m2\目录
-
国内镜像下载解压
-
配置:
- 在conf目录下找到settings.xml文件,设置镜像地址
- 在conf目录下找到settings.xml文件,设置镜像地址
设置本地maven下载jar后默认的保存位置
使用mybatis
idea设置maven
设置maven文件夹存在地址与设置文件所在地址,如果设置了jar包存储仓库,会自动识别
新建一个项目,点击maven,如果使用maven,就把create from archetype勾打上,我们只是用mybatis框架因此不打勾,点击next
设置项目名称和保存项目路径
main中的resources存放配置文件;java存放java包、类、接口;test用于测试;pom.xml用来描述将要用到的信息
构建一个小mybatis项目,首先下载一个插件:mybatisCodeHelperPro用于sql提示,有代码提示
连接数据库需要mybatis的配置定义文件,我们可以去网上找mybatis头部文件,复制头部配置
Mybatis xml文件头 - Actexpler - 博客园 (cnblogs.com)
报红是因为maven没有引用关于mybatis的设置,我们要去https://mvnrepository.com/去搜索mybatis,将mybatis的jar包引用到pom.xml下
将mybatis的jar包写到maven的pom.xml中,pom.xml添加各种jar包
接着添加mysql的jar包(5.1.0版本)、Junit jar包(单元测试)、log4j的jar包
resources中创建配置文件mybatis-config.xml
,用于创建数据源,与数据库连接 ; 导入日志;导入数据库的配置文件database.properties ;mapper的xml文件的引用,更简单化创建一个包,告诉目录的位置即可
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis对数据库信息定义-->
<configuration>
<!--引入database配置文件-->
<properties resource="database.properties"></properties>
<!-- 配置mybatis的日志实现为log4j-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!-- 创建数据源,connection,JDBC来进行事务管理-->
<environments default="development">
<environment id="development">
<!-- 配置事务管理 JDBC来进行事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED:mybatis自带的数据源,JNDI:基于tomcat的数据源-->
<dataSource type="POOLED">
<!-- 此处的value="${driver}"与数据库配置文件的属性一致-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--将mapper的xml文件加入到mybatis配置文件中-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"></mapper>
</mappers>
</configuration>
resources中创建log4j的配置文件,用于存储日志的定义
resources中创建数据库的配置文件database.properties 存储数据库登录驱动信息
实现mybatis配置文件中对于xml文件的引用 : resources下新建一个文件夹mapper,mapper里面创建一个xml,xml文件用于写访问数据库的方法,起一个名,有要求,如果对student进行操作,就起名为StudentMapper.xml,此xml文件名与Dao层接口文件名一致,这个xml文件有格式的设置,需要我们从网上找:mybatis映射文件mapper.xml的写法
namespace表示当前mapper的位置或者接口
<?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=""></mapper>
Dao层创建接口文件名为StudentMapper.java
,与要实现接口方法的xml文件名一致,StudentMapper.xml中的id就是用于对应接口文件写的方法名,因此接口方法必须与StudentMapper.xml中的一个id名称相同,才能匹配到,这样StudentMapper.xml就可以实现这个接口方法了
练习:对于学生表的操作
练习一:查询学生人数
-
Dao层接口文件
StudentMapper.java
,定义查询学生人数的方法:int getStudentCount();
-
StudentMapper.xml可以写一些数据库访问语句:id为接口文件定义的方法名 resultType表示返回值类型
<select id="getStudentCount" resultType="int">
select count(1) from student;
</select>
- 去mybatis-config.xml与mapper文件产生映射
<!--将mapper的xml文件加入到mybatis配置文件中-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"></mapper>
</mappers>
- test中创建一个测试类,使用sqlsession访问数据库
public class StuTest {
//加入日志
private Logger logger=Logger.getLogger(StuTest.class.getName());
@Test
public void testA() throws IOException {
//使用mybatis,将mybatis配置文件转换为输入流,用于获取mybatis配置文件信息
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//导入配置信息 获取sqlsessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//通过sqlsessionFactory获取sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession可以用于执行数据库的访问操作
Object count = sqlSession.selectOne("mapper.StudentMapper.getStudentCount");
//日志保留访问数据库的结果
logger.debug("学生人数为:"+count);
//一定要关闭
sqlSession.close();
}
练习二:根据学生姓名进行模糊查询
-
首先要在实体层中创建一个学生类,学生类属性与数据库表student的设计表属性顺序一致,实体层在main中的java下名为pojo
-
Dao层接口文件定义一个根据学生姓名进行模糊查询的方法
List<Student> getStuName(String studentName);
,返回一个学生对象集合 -
StudentMapper.xml可以写一些数据库访问语句:id为接口文件定义的方法名 ,由于返回结果为学生对象集合,因此resultType设置为集合元素类型:学生对象
<!--#{studentName}参数来自接口,接口的方法名与此处id一致-->
<select id="getStuName" resultType="pojo.Student">
select * from student where studentName like concat('%',#{studentName},'%');
</select>
- 测试:
@Test
public void testC() throws IOException {
//使用mybatis,将mybatis配置文件转换为输入流,用于获取mybatis配置文件信息
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//导入配置信息 获取sqlsessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//通过sqlsessionFactory获取sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession可以用于执行数据库的访问操作 selectList返回一个集合
//List<Student> studentlist = sqlSession.selectList("mapper.StudentMapper.getStuAll");//这样写由于接口存在值会指向接口不返回此处
List<Student> studentlist = sqlSession.getMapper(StudentMapper.class).getStuName("李");//直接获取这个接口中的方法
//日志保留访问数据库的结果
for (Student stu:studentlist){
logger.debug("学生名称为:"+stu.getStudentName());
}
//一定要关闭
sqlSession.close();
}
练习三:对象当作参数查询
-
接口定义方法
-
为了简化xml中接口类型resultType的描述,在mybatis-config.xml配置文件中配置别名
-
xml中实现接口方法
-
测试
练习四:使用map集合当作参数
练习五:参数为list的查询
//使用List传参
List<Student> QueryStudent_C(List<String> list);
<!-- 参数为List集合的查询 参数类型写全包名java.util.ArrayList List需要遍历 collection="接口参数名" -->
<select id="QueryStudent_C" resultType="Student" parameterType="java.util.ArrayList">
select * from student
where studentNo in(
<foreach collection="list" item="stuNo" index="index" separator=",">
#{stuNo}
</foreach>
)
</select>
@Test
public void testG() throws IOException {
//使用mybatis,将mybatis配置文件转换为输入流,用于获取mybatis配置文件信息
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//导入配置信息 获取sqlsessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//通过sqlsessionFactory获取sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
List<String> stuNos = new ArrayList<String>();
stuNos.add("10001");
stuNos.add("10005");
stuNos.add("10008");
List<Student> studentlist = sqlSession.getMapper(StudentMapper.class).QueryStudent_C(stuNos);//直接获取这个接口中的方法
//日志保留访问数据库的结果
for (Student stu:studentlist){
logger.debug("学生名称为:"+stu.getStudentName());
}
//一定要关闭
sqlSession.close();
}
练习六:数组入参 需要加入注解
//使用数组传参 引用数据类型需要加入注解
List<Student> QueryStudent_D(@Param("stuNos") int[] stuNos);
<!-- 参数为数组的查询 不用写参数类型-->
<select id="QueryStudent_D" resultType="Student">
select * from student
where studentNo in(
<foreach collection="stuNos" item="stuNo" index="index" separator=",">
#{stuNo}
</foreach>
)
</select>
描述如下:
@Test
public void testH() throws IOException {
//使用mybatis,将mybatis配置文件转换为输入流,用于获取mybatis配置文件信息
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//导入配置信息 获取sqlsessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//通过sqlsessionFactory获取sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
int[] stuNos={10001,10005,10008};
List<Student> studentlist = sqlSession.getMapper(StudentMapper.class).QueryStudent_D(stuNos);//直接获取这个接口中的方法
//日志保留访问数据库的结果
for (Student stu:studentlist){
logger.debug("学生名称为:"+stu.getStudentName());
}
//一定要关闭
sqlSession.close();
}
由于测试创建sqlsession有过多重复代码,因此简化一个工具类
package 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 MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
public MyBatisUtil() {
}
public static void closeSqlSession(SqlSession sqlSession) {
if (null != sqlSession) {
sqlSession.close();
}
}
static {
System.out.println("创建SqlSessionFactory------------------------");
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//导入配置信息 获取sqlsessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession createSqlSession() {
return sqlSessionFactory.openSession(false);//设置自动关闭 用于事务处理}
}
}
练习:对于年级表的增删改
-
pojo实体层创建年级类
-
dAO中创建GradeMapper接口写方法
-
mapper中创建GradeMapper.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="dao.GradeMapper">
<insert id="addGrade" parameterType="String">
insert into grade (gradeName)values (#{gradeName})
</insert>
<delete id="deleteGrade" parameterType="int"
>
delete from grade where gradeId=#{gradeId}
</delete>
<update id="updateGrade" parameterType="Grade">
update grade set gradeName=#{gradeName} where gradeId=#{gradeID}
</update>
</mapper>
- 配置文件进行年级mapper文件映射
<!--将mapper的xml文件加入到mybatis配置文件中-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"></mapper>
<mapper resource="mapper/GradeMapper.xml"></mapper>
</mappers>
- 测试
@Test
public void testA(){
SqlSession sqlSession = MyBatisUtil.createSqlSession();
//int row = sqlSession.getMapper(GradeMapper.class).addGrade("初一");
//int row = sqlSession.getMapper(GradeMapper.class).deleteGrade(4);
int row = sqlSession.getMapper(GradeMapper.class).updateGrade(new Grade(5,"六年级"));
if (row!=0){
sqlSession.commit();
System.out.println("success");
}else{
sqlSession.rollback();
System.out.println("fail");
}
MyBatisUtil.closeSqlSession(sqlSession);
}
由于每次创建mapper下的xml文件头部信息需要去网上查找或者复制,因此我们可以自动一个模板
- 创建xml文件直接使用这个模板
有难度的复杂查询动态SQL语句
练习一:查询学生表获取年级名称
年纪名称在年级实体类里面,查询学生需要用到年级实体类,查询一个学生,找到一个年级,学生与年级是一对一关系,学生表gradeId外键关联年级表gradeID
那么查询学生如何获取年级信息呢?
-
首先创建学生实体类、年级实体类
-
学生实体类中创建年级对象属性与get、set方法,通过映射将查询的信息保存到年级对象中。映射关系为:查询一个学生,找到一个年级,查询年级对象,找到一个学生集合
-
接口文件写查询方法
//查询学生信息,获取学生年级名称
List<Student> QueryStudent_E();
- xml文件实现方法: 返回结果为自定义id的resultMap,resultMap中设置主键列id(表中的列名column(如果过长可以自己起一个名字)、实体对象属性名propertity、查询的是哪个对象,type就写这个对象的真实类型Student),需要的副键列,
- 最重要的是在resultMap中描述学生与年级的关系association,学生实体中有一个年纪对象,设置实体类学生的属性名年级对象property,实体类学生的属性名的真实类型javaType(此处为实体类年级),association中写需要的年级主副键列(年级实体类的属性名pro perty与表列名column),如果不填就是全都都要
- 把返回结果为自定义id的resultMap设置到mapper映射中,查询到的年级信息就会保存到学生实体类中的年纪对象属性中,就可以通过查询年级对象获取年级名称属性值
- 测试:做了映射后,查询到的年级信息就会保存到学生实体类中的年纪对象属性中
练习二:查询学生表获取年级名称与学生考试成绩
一个学生可以考多次试,因此一个学生有多个考试成绩结果,学生与成绩是一对多关系,且学生表学生编号主键关联成绩表学生编号
- 创建成绩实体类
- 由于一个学生有多个考试成绩,因此学生实体类创建返回一个成绩实体类对象的集合、get set方法
//一个学生有多个成绩,因此一个学生对应多个成绩对象,一对多关系,创建成绩集合
private List<Result> resultList;
- 查询的对象为学生实体类,学生与成绩为一对多关系,使用关系为collection,设置学生实体类属性名成绩集合property,与学生实体类属性名所在类型(成绩实体类)ofType
- mapper做映射
练习三:查询学生,查看学生成绩属于哪个科目
成绩表中外键subjectNo关联了科目表主键subjectNo,每一项成绩都可以查到所对应的科目,从成绩到科目是一对一关系,因此就可以通过查询学生来获取学生成绩属于哪个科目。
这是一种嵌套查询,首先通过学生表查询成绩表,再通过成绩表查询科目表。
- 创建科目实体类,成绩实体类创建科目对象
- mapper中,学生成绩关系collection中嵌套查询科目,成绩与科目关系为association 一对一
<sql id="sql_stu_resu_subj">
select * from student
join grade
on grade.gradeID=student.gradeId
join result
on student.studentNo=result.studentNo
join `subject`
on result.subjectNo=`subject`.subjectNo
</sql>
<!-- 查询学生表获取年级名称 查询学生表返回学生对象集合,type为学生对象 -->
<!-- Type:查询学生表,此处为学生实体类,查询成绩表,此处为成绩实体类 -->
<resultMap id="studentMap" type="Student">
<id column="studentNo" property="studentNo"></id>
<result column="studentName" property="studentName"></result>
<result column="phone" property="phone"></result>
<!-- 学生年级一对一 使用association关系 描述需要的年级表属性 property="grade" 实体类属性名 -->
<association property="grade" javaType="pojo.Grade">
<id column="gradeID" property="gradeID"></id>
<result column="gradeName" property="gradeName"></result>
</association>
<!--学生成绩一对多 使用collection关系 描述需要的成绩表属性-->
<collection property="resultList" ofType="pojo.Result">
<result column="studentNo" property="studentNo"></result>
<result column="subjectNo" property="subjectNo"></result>
<result column="examDate" property="examDate"></result>
<result column="studentResult" property="studentResult"></result>
<!-- 嵌套查询科目表 科目表与成绩表主外键关联 -->
<association property="subject" javaType="Subject">
<id column="subjectNo" property="subjectNo"></id>
<result column="subjectName" property="subjectName"></result>
<result column="classHour" property="classHour"></result>
</association>
</collection>
</resultMap>
- 测试
复杂查询总结:查询结果为对象使用的关系为association,查询结果为集合使用的关系为collection
多条件复杂动态SQL查询
例如按照如下多条件查询,有一种情况是所有条件值为空,就是全部查询;其余情况是满足其中一种条件的动态查询
- 查询接口定义方法,传入参数类型为Map集合
//查询学生信息,多条件if查询学生
List<Student> QueryStudent_F(Map<String,String> map);
Mybatis提供的方式如下:多条件每一项要加入AND,mybatis会自动拼接和删除多余AND,如果每一次访问数据库的方法中都有重复的sql语句,可以抽取出来引用
<select id="QueryStudent_F" resultMap="studentMap">
<include refid="sql_stu_resu_subj">
</include>
<where>
<if test="studentName!=''">
AND student.studentName like concat('%',#{studentName},'%')
</if>
<if test="phone!=''">
and student.phone=#{phone}
</if>
<if test="gradeName!=''">
and grade.gradeName=#{gradeName}
</if>
<if test="subjectName!=''">
and `subject`.subjectName=#{subjectName}
</if>
</where>
</select>
- 测试
Map集合的键名必须与mapper.xml
中传入的参数名一致,才能对应匹配查询该条件值是否存在,存在就填充SQL语句中查询
@Test
public void testJ() throws IOException {
SqlSession sqlSession = MyBatisUtil.createSqlSession();
Map<String, String> map = new HashMap<String, String>();
map.put("studentName","李");
map.put("phone","");
map.put("gradeName","");
map.put("subjectName","");
List<Student> studentlist = sqlSession.getMapper(StudentMapper.class).QueryStudent_F(map);//直接获取这个接口中的方法
//学生集合中遍历每一个学生,获取学生姓名、年级、成绩对象集合
for (Student stu:studentlist){
logger.debug("学生名称为:"+stu.getStudentName()+" 学生年级:"+stu.getGrade().getGradeName());
for (Result result:stu.getResultList()){
logger.debug("考试时间: "+result.getExamDate()+
"考试成绩: "+result.getStudentResult()+
"科目:"+result.getSubject().getSubjectName()); }
}
//一定要关闭
MyBatisUtil.closeSqlSession(sqlSession);
}
练习四:使用if-else来筛选多条件进行动态SQL查询
- 接口定义方法
//查询学生信息,多条件筛选if-else查询学生
List<Student> QueryStudent_G(Map<String,String> map);
只要进入一个判断中其余判断均不进入
- 测试
练习五:对学生表的添加修改复杂动态sql语句
- 接口定义方法
//通过学生对象添加学生到数据库中,返回影响行数
int addStudent(Student student);
//通过学生对象修改学生到数据库中,返回影响行数
int updateStudent(Student student);
- mapper下:添加语句中有的列不允许为空,使用一个对象来写添加的值
<insert id="addStudent" parameterType="Student">
INSERT INTO `student` (
`studentNo`,
`loginPwd`,
`studentName`,
`sex`,
`gradeId`,
`phone`,
`address`,
`bornDate`,
`email`,
`identityCard`
)
<trim prefix="VALUES (" suffix=");" prefixOverrides="," suffixOverrides=",">
#{studentNo},
#{loginPwd},
#{studentName},
#{sex},
#{gradeId},
#{phone},
#{address},
#{bornDate},
#{email},
#{identityCard},
</trim>
</insert>
- 修改语句
利用前缀后缀标签来写修改SQL语句:
<update id="updateStudent" parameterType="Student">
UPDATE `student`
<!-- 修改语句写法一: <set></set><where></where>-->
<!-- 修改语句使用前后缀写法二:-->
<trim prefix="set" suffix="WHERE(`studentNo` =#{studentNo})" suffixOverrides=",">
<if test="loginPwd!=null and loginPwd!=''">
`loginPwd` = #{loginPwd},
</if>
<if test="studentName!=null and studentName!=''">
`studentName` = #{studentName},
</if>
<if test="sex!=null and sex!=''">
`sex` = #{sex},
</if>
<if test="gradeId!=0">
`gradeId` = #{gradeId},
</if>
<if test="phone!=null and phone!=''">
`phone` = #{phone},
</if>
<if test="address!=null and address!=''">
`address` = #{address},
</if>
<if test="bornDate!=null and bornDate!=''">
`bornDate` = #{bornDate},
</if>
<if test="email!=null and email!=''">
`email` = #{email},
</if>
<if test="identityCard!=null and identityCard!=''">
`identityCard` = #{identityCard},
</if>
</trim>
</update>
- 测试:
@Test
public void testL() throws IOException {
SqlSession sqlSession = MyBatisUtil.createSqlSession();
Student student=new Student(
1119,
"1111",
"scq11",
"女",
1,
"",
"",
"1901-9-8",
"",
"610103199609050028");
int row = sqlSession.getMapper(StudentMapper.class).addStudent(student);//直接获取这个接口中的方法
if (row!=0){sqlSession.commit();}
else{sqlSession.rollback();}
System.out.println(row==0?"失败":"成功");
//一定要关闭
MyBatisUtil.closeSqlSession(sqlSession);
}
@Test
public void testM() throws IOException {
//将30016这个学生性别修改为男
SqlSession sqlSession = MyBatisUtil.createSqlSession();
Student student=new Student();
student.setStudentNo(30016);
student.setSex("男");
int row = sqlSession.getMapper(StudentMapper.class).updateStudent(student);//直接获取这个接口中的方法
if (row!=0){sqlSession.commit();}
else{sqlSession.rollback();}
System.out.println(row==0?"失败":"成功");
//一定要关闭
MyBatisUtil.closeSqlSession(sqlSession);
}
}
MyBatis缓存
MyBatis提供了一级缓存来减轻数据库压力但是一级缓存是SqlSession(会话)级别的缓存,
意味着一级缓存的适用范围比较小。
在一级缓存的基础上,MyBatis提供了二级缓存二级缓存是namaspace级别的缓存机制相对一一级缓存
二级缓存允许跨SqlSession工作,因此二级换的作用范围更大。
二级缓存的机制:
每个SqlSession在执行查询操作时,都会将查询的结果放在当前的会话(一级缓存中),如果当前会话关闭,一级缓存中的数据会被保存在二级缓存中。因此二级缓存是在一级缓存的基础上进行扩展的,不同的namaspace查出的数据都会将数据存在自己对应的缓存中,这些缓存信息使用map存储。
注意:MyBatis在开启二级缓存的清下,如果发出来一条SQL查询语句,会先向二级缓存中查询是否存在对应的缓存数据,如果没有 接着查询一级缓存中的数据,如果一级缓存中也没有对应的缓存数据,才会向数据库发送SQL语句。
实现:
1、在MyBatis全局配置(mybatis-config.xml)文件中开启二级缓存的配置(默认也是开启的)
2、在对应的SQL映射文件中加入 < cache / >标签。
3、将返回的JavaBean(实体类)实现序列化接口implements Serializable,序列化:将对象变成数据方便传输
测试:第一次查询完不关闭sqlsession进行二次查询,查询是从一级缓存中查询的
第一次查询完关闭sqlsession,查询结果保存到二级缓存中。第二次查询重新创建sqlsession,但是测试结果没有显示SQL语句,说明是从二级缓存中查询的
测试结果:第一次查询先去一级缓存,一级缓存没有去数据库查询,数据库查询后保存到一级缓存中,一级缓存在sqlsession关闭时保存到二级缓存中,第二次查询先去二级缓存查(不显示SQL语句),查询到后展示结果