Mybatis持久层应用框架


MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。


Mybatis核心组件:
SqlSessionFactoryBuilder:会根据配置信息或代码来生成SqlSessionFactory;
SqlSessionFactory:依靠工厂来生成SqlSession;
SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口;
SQL Mapper:是MyBatis新设计的组件,由一个Java接口和XML文件构成,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。

//加载配置文件到输入流
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
   //通过sqlsession工厂构建器加载资源配置文件构建 sqlsession工厂类
   SqlSessionFactory  sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
   //通过工厂创建sqlsession对象
   SqlSession sqlSession = sqlSessionFactory.openSession();
   //通过sqlSession获取映射的Dao接口对象
   StudentDao studentDao= sqlSession.getMapper(StudentDao.class);
    //直接可以调用接口中定义的方法
   studentDao.deleteStudent(1);
 //手动提交事务,如要自动提交事务,需在sqlSessionFactory.openSession(true);添加true参数为自动提交
   sqlSession.commit();
 //关闭sqlSession
   sqlSession.close();
 //关闭输入流
   inputStream.close();

单元测试JUnit

junit4中常用注解 @BeforeClass @Before @AfterClass @After @Test @Ignore
junit5中常用注解 @BeforeAll @BeforeEach @AfterAll @ AfterEach @Test

junit5 单元测试类:

class TestMyBatis {
	static InputStream resourceAsStream;
	static SqlSession sqlSession;
	//第四步、通过sqlsession获取接口
	static StudentDao studentDao;
	@BeforeAll
	static void init() throws Exception{
          //第一步、通过resource获取mybatis的全局配置文件加载到输入流中
          resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
          //第二步、使用工厂构建器通过全局配置文件mybatis-config.xml创建出一个sqlsession的工厂类
          SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resourceAsStream);
          //第三步、使用工厂创建出sqlsession
          //SqlSession sqlSession = sqlSessionFactory .openSession();
          //设置sqlsession自动提交事务,加一个参数true,不需要使用commit()
          sqlSession = sqlSessionFactory .openSession(true);
          //第四步、通过sqlsession获取接口
          studentDao = sqlSession.getMapper(StudentDao.class);
	}
	
	@Test
	void testSelectStudentById() throws Exception{
		Student student = studentDao.selectStudentById(3);
		System.out.println(student);	
	}
	
	@Test
	void testSelectAllStudents() throws Exception{
		List<Student> ls = studentDao.selectAllStudents();
		for(Student student : ls)
		System.out.println(student);
	}

	@Test
	void testUpdateStudent() throws Exception{
		Student student = new Student(3,"李四",18);
		int result = studentDao.updateStudent(student);
		System.out.println(result);
	}
	
	@Test
	void testDeleteStudent() throws Exception{
		int result = studentDao.deleteStudent(2);
		System.out.println(result);
	}
	
	@Test
	void testInsertStudent() throws Exception{
		int result = studentDao.insertStudent(new Student(4,"王六",23));
		System.out.println(result);

	}
	@AfterAll
	static  void close() throws Exception{
		sqlSession.close();
		resourceAsStream.close();	
	}
}

junit4:

public class JunitTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("in before class");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("in after class");
    }

    @Before
    public void before() {
        System.out.println("in before");
    }

    @After
    public void after() {
        System.out.println("in after");
    }

    @Test
    public void testCase1() {
        System.out.println("in test case 1");
    }

    @Test
    public void testCase2() {
        System.out.println("in test case 2");
    }

}

在这里插入图片描述

Mybatis增删改查

修改接口和映射文件

<mapper namespace="org.lanqiao.mapper.StudentMapper">
	<insert id="insertStudent" parameterType="Student">
		insert into student values(null,#{sname},#{sage})
	</insert>
	<delete id="deleteStudent" parameterType="Integer">
		delete from student where sid = #{nid}
	</delete>
	<delete id="deleteStudent2" parameterType="Student">
		delete from student where sid = #{sid}
	</delete>
	<update id="updateStudent" parameterType="Student">
		update student set sname=#{sname},sage=#{sage} where sid=#{sid}
	</update>
	
	<select id="selectStudentById" parameterType="int" resultType="Student">
		select * from student where sid = #{id}
	</select>
	<select id="selectAllStudents" resultType="Student">
		select * from student
	</select>
</mapper>

查询进阶

假如实体类Student sname ----》表student name 名字不一样怎么办?
假如sql是一个复杂的多表查询时,Student类无法完全匹配怎么办?

1.Resultmap的应用:

<resultMap type="Student" id="StudentResultMap">
	<id property="id" column="sid" javaType="int" jdbcType="NUMERIC"/>
        <result property="name" column="sname" javaType="String" jdbcType="VARCHAR"/>
        <result property="age" column="sage" javaType="int" jdbcType="NUMERIC"/>
  </resultMap>

作用:a.解决当实体类中包含其他的实体类时一种映射关系
b.当数据库的字段名和实体类的属性名不一致时
2.多表查询:
注:表的名字尽量不要使用关键字,比如分组表group,group就是SQL的一个关键字假如要使用的话,只能在group,该`是键盘tab上面的那个按键

(1).一对一 association
学生表关联年级表(一对一关系)

对应的sql:

select * from student s,grade g where s.gid=g.gid
<resultMap type="Student" id="StudentResultMap">
	<id property="id" column="sid" javaType="int" jdbcType="NUMERIC"/>
        <result property="name" column="sname" javaType="String" jdbcType="VARCHAR"/>
        <result property="age" column="sage" javaType="int" jdbcType="NUMERIC"/>
       <association property="grade" column="gradeid" select="org.lanqiao.mapper.GradeMapper.selectGradeById"  />
</resultMap>

这种做法的问题:sql语句变多,执行的次数增加,解决该问题使用:延迟加载(懒加载)、按需加载
需要修改全局配置文件mybatis-config.xml

 <!--延迟加载,按需加载,需要什么就查什么,不需要的不会去查询-->	
 <settings>
		<setting name="lazyLoadingEnabled" value="true"/>
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings>

动态sql 动态SQL是基于OGNL(Object-Graph Navigation Language)表达式

动态sql主要功能:拼接SQL语句

做搜索功能
if

          <if test=”id!=null and id!='“>
			and sid = #{id}
		</if>
		<if test="name!=null and name!=''">
			and sname like <bind name="name" value="'%'+_parameter.getName() +'%'"/>
		</if>
		<if test="age!=null and age!=''">
			and sage = #{age}
		</if>

模糊查询:
1.程序处理查询字符串stu.setName("%张%");
2.利用数据库的Concat函数 sname like CONCAT(CONCAT(’%’,#{name}),’%’),mysql和oracle都支持的
3.Mybatis提供bind动态sql

<bind name="name2" value="'%'+_parameter.getName() +'%'"/>

可以通过#{name2}取到value的值

4.使用 方 式 a n d s n a m e l i k e ′ {}方式 and sname like '% andsnamelike{name}%’ “a or 1=1 and”
使用场景 select * from student order by ${sname}
根据一个字段进行查询排序
selectAllStudentOrderBy(String field);

注: 取 字 符 串 参 数 使 用 {}取字符串参数使用 使{value}或${_parameter}

 select * from student order by name     //${field}
    select * from student order by "name"  //#{field}
<select>
  	select * from student order by #{field}
</select>

mybatis缓存机制 cache

  1. 一级缓存
    有效范围:sqlsession
    针对:查询操作
    默认:开启
    写入时间:查询后即写入缓存
    如何判断使用一级缓存,根据你的执行sql和你传入的参数在sqlsession有效范围内
    手动清除一级缓存:
    1.sqlsession.close()
    2.sqlsession.clearCache();
    3.执行了insert,update,delete都会清除缓存
  2. 二级缓存
    有效范围:设定全局,使用中有效范围是在一个namespace当中
    针对:查询
    默认:关闭
    写入缓存时间:当查询完毕,关闭sqlsession才会写入缓存
    二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的
    因为被缓存的内容即对象需要保存到硬盘,就需要给对应的实体类进行序列化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值