Mybatis

一、MyBatis原理
1、核心

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件一个预先配置的 Configuration 实例构建出 SqlSessionFactory 实例

2、作用域和生命周期
  • SqlSessionFactoryBuilder

    这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

  • SqlSessionFactory

    SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式

  • SqlSession

    每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。返回一个响应后,就关闭它。 这个关闭操作很重要

  • 映射器实例

    映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。 也就是说,映射器实例应该在调用它们的方法中被获取,使用完毕之后即可丢弃。 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,在这个作用域上管理太多像 SqlSession 的资源会让你忙不过来。 因此,最好将映射器放在方法作用域内。

二、构建一个简单的MyBatis项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zseAjcsX-1609828347456)(C:\Users\张聪\AppData\Roaming\Typora\typora-user-images\1608530853124.png)]

1、创建数据库表
2、导入mybatis相关jar包
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
<dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
<dependency>
3、编写mybatis-config核心配置文件

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器

XML 头部的声明,它用来验证 XML 文档的正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息

<?xml version="1.0" encoding="UTF-8" ?>
<!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/demo?useSSL = true&amp;useUnicode = true&amp;characterEnconding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
      </dataSource>
    </environment>
  </environments> -->
    <!--数据源配置第二种方法直接配置-->
    <!--在src下新建一个properties文件,里面填写数据源参数,然后通过<properties>标签引入进来-->
  <properties resource="db.properties"></properties>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
    
    
  <mappers>
    <mapper resource="com/zc/data/mapper.xml"/>
  </mappers>
</configuration>
4、编写mybatis工具类
public class MybatisUtil {
	private static SqlSessionFactory sqlSessionFactory;
	static {
		try{
            //通过MyBatis下的Resources工具类获得一个输入流,来获取SqlSessionFactory对象
			String resource = "com/zc/data/mabatis-config.xml";
			InputStream inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		} catch(Exception e){
			e.printStackTrace();
		}
		
	}
	//获取sqlsession连接,SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
	public static SqlSession getSession() {
		return sqlSessionFactory.openSession();
	}
	
}
5、创建实体类
public class Hero {
	private String name;
	private int age;
	private String position;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPosition() {
		return position;
	}
	public void setPosition(String position) {
		this.position = position;
	}
	@Override
	public String toString() {
		return "Hero [name=" + name + ", age=" + age + ", position=" + position + ", getName()=" + getName()
				+ ", getAge()=" + getAge() + ", getPosition()=" + getPosition() + "]";
	}
	
}
6、编写mapper接口类
public interface HeroMapper {
	//查询所有
	List<Hero> selectAll();
}
7、编写mapper.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">
<!--这里是通过命名空间namespace进行映射查找的-->
<mapper namespace="com.zc.mapper.HeroMapper">
  <select id="selectAll" resultType="com.zc.entity.Hero">
    select * from hero
  </select>
</mapper>
8、测试类
public class Test01 {
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
		List<Hero> heros = mapper.selectAll();
		for (Hero hero : heros) {
			System.out.println(hero);
		}
		sqlSession.close();
	}
}
三、MyBatis的CURD
  • 接口类

    public interface HeroMapper {
    	//查询所有
    	List<Hero> selectAll();
    	//根据一个条件查
    	Hero selectByName(String name);
    	//根据多个条件查,参数前要加上@Param属性,这样映射时就以param中的为准了
    	Hero selectByNameAndPositon1(String name,String position);//不可行
    	Hero selectByNameAndPositon2(@Param("name")String 		            nameString,@Param("position")String position);
    	Hero selectByNameAndPositon3(Map map);
    	//增加一个用户
    	int addHero(Hero hero);
    	//修改一个用户
    	int updateHero(Hero hero);
    	//删除一个用户
    	int deleteHero(@Param("name")String name);
    	
    }
    
  • mapper.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="com.zc.mapper.HeroMapper">
      <select id="selectAll" resultType="com.zc.entity.Hero">
        select * from hero
      </select>
      <select id="selectByName" resultType="com.zc.entity.Hero">
        select * from hero where name=#{name}
      </select>
      <select id="selectByNameAndPositon1" resultType="com.zc.entity.Hero">
        select * from hero where name=#{name} and position = #{position}
      </select>
      <select id="selectByNameAndPositon2" resultType="com.zc.entity.Hero">
        select * from hero where name=#{name} and position = #{position}
      </select>
      <select id="selectByNameAndPositon3" resultType="com.zc.entity.Hero">
        select * from hero where name=#{name} and position = #{position}
      </select>
      
      <!-- 增加 -->
      <insert id="addHero">
        insert into hero (name,age,position) values (#{name},#{age},#{position})
      </insert>
      
      <!-- 修改 -->
      <update id="updateHero">
        update hero set age=#{age} where name=#{name}
      </update>
      
      <!-- 删除 -->
      <delete id="deleteHero">
        delete from hero where name=#{name}
      </delete>
    </mapper>
    
  • 测试代码

    public class Test01 {
    	public static void main(String[] args) {
    		SqlSession sqlSession = MybatisUtil.getSession();
    		HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
    		/**
    		 *查询所有
    		 */
    //		List<Hero> heros = mapper.selectAll();
    //		for (Hero hero : heros) {
    //			System.out.println(hero);
    //		}
            
    		/**
    		 *按一个条件进行查询
    		 */
    //		Hero hero = mapper.selectByName("韩信");
    //		System.out.println(hero);
    
    //		//第二种写法
    //		Hero hero2 = (Hero)MybatisUtil.getSession().selectOne(
            "com.zc.mapper.HeroMapper.selectByName", "韩信");
    //		System.out.println(hero2);
            
    		/**
    		 * 按多个条件进行查询
    		 */
    		//使用@Param属性
    //		Hero hero = mapper.selectByNameAndPositon2("李白", "刺客");
    //		System.out.println(hero);
    		//使用Map作为参数传值
    //		Map map = new HashMap<String , String>();
    //		map.put("name", "李白");
    //		map.put("position", "刺客");
    //		Hero hero = mapper.selectByNameAndPositon3(map);
    //		System.out.println(hero);
    		
    		/**
    		 * 新增
    		 */
    //		Hero hero = new Hero();
    //		hero.setAge(25);
    //		hero.setName("澜朋友");
    //		hero.setPosition("刺客");
    //		int index= mapper.addHero(hero);
    //		System.out.println(index);
    //		sqlSession.commit();//提交事务,不执行的话不会提交到数据库。增删改都要提交事务
    		
    		/**
    		 * 修改
    		 */
    //		Hero hero = new Hero();
    //		hero.setAge(100);
    //		hero.setName("澜朋友");
    //		hero.setPosition("刺客");
    //		int index = mapper.updateHero(hero);
    //		System.out.println(index);
    //		sqlSession.commit();
    		
    		/**
    		 * 删除
    		 */
    		int index = mapper.deleteHero("聪聪");
    		System.out.println(index);
    		sqlSession.commit();
    		sqlSession.close();
    	}
    }
    
四、ResultMap及分页
1、当数据库中的表字段与实体类中属性字段不一致时,可以通过ResultMap来进行映射。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uPqCTERz-1609828347460)(C:\Users\张聪\AppData\Roaming\Typora\typora-user-images\1609314184413.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JxBxfpa3-1609828347463)(C:\Users\张聪\AppData\Roaming\Typora\typora-user-images\1609314226745.png)]

//public class Test01 {
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
		Hero hero = (Hero)mapper.selectHeroByAge(25);
		System.out.println(hero);
	}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-afWdMXLg-1609828347468)(C:\Users\张聪\AppData\Roaming\Typora\typora-user-images\1609314295641.png)]

查询出的名字为null==>原因:mybati会根据查询的列名去对应的实体类中查找相应列名的set方法设值,找不到,所以返回null。

解决办法:

1、为不一样的列名指定别名,别名与实体类的属性字段一致

<mapper namespace="com.zc.mapper.HeroMapper">
    <select id="selectHeroByAge" resultType="com.zc.entity.Hero">
        select name as heroname,age,position from hero where age = #{age}
    </select>
</mapper

2、使用结果映射集–ResultMap

属性描述
property需要映射到JavaBean的属性名称
column数据表的列名或者标签别名
javaType一个完整的类名或类型别名
jdbcType数据表支持的类型列表。该属性只在insert、update、delete时针对允许空的列有用。
typeHandler使用这个属性可以覆写类型处理器。可以是一个完整类名,也可以时一个类型别名。
<mapper namespace="com.zc.mapper.HeroMapper">
    <!--结果映射集-->
    <resultMap id="hero" type="com.zc.entity.Hero">
        <!--主键-->
        <!--<id column="" property></id>-->
        <!--column对应数据库,property对应实体类-->
        <result column="name" property="heroname"/>
        <result column="age" property="age"/>
        <result column="property" property="property"/>
    </resultMap>
    <!--结构集使用resultMap-->
    <select id="selectHeroByAge" resultMap="hero">
        select name,age,position from hero where age = #{age}
    </select>
</mapper>
2、分页
  • 使用limit进行分页
#从第startindex开始,每次查pagesize条
select * from hero limit startindex,pagesize;
public interface HeroMapper {
	List<Hero> selectpage(Map map);
}

 
    <!-- 分页查询 -->
    <select id="selectpage" resultType="com.zc.entity.Hero">
        select * from hero limit #{currentpage},#{pagesize}
    </select>
public class Test01 {
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
		Map map = new HashMap();
		int currentpage=1;//当前页
		int pagesize=2;//每页显示记录数
		map.put("currentpage", currentpage);
		map.put("pagesize", pagesize);
		List<Hero> list = mapper.selectpage(map);
		for (Hero hero : list) {
			System.out.println(hero);
		}
		sqlSession.close();
	}
}
/**
Hero [name=null, age=50, position=刺客, getName()=null, getAge()=50, getPosition()=刺客]
Hero [name=null, age=25, position=战士, getName()=null, getAge()=25, getPosition()=战士]
*/

  • mybatis分页插件 PageHelper
五、注解

1、sql类型

  • @select()
  • @update()
  • @insert()
  • @delete()

利用注解开发就不需要mapper.xml映射文件了

public interface HeroMapper {
	@Select("select * from hero")
	List<Hero> selectHeros();
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <properties resource="db.properties"></properties>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <!--
  <mappers>
    <mapper resource="com/zc/data/mapper.xml"/>
  </mappers>
    -->
    <!--mapper不再时mapper.xml文件-->
   <mappers>
    <mapper class="com.zc.mapper.HeroMapper"/>
  </mappers>
</configuration>

public class Test01 {
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		HeroMapper mapper = sqlSession.getMapper(HeroMapper.class);
		List<Hero> list = mapper.selectHeros();
		
		for (Hero hero : list) {
			System.out.println(hero);
		}
		sqlSession.close();
	}
}

六、一对多与多对一处理

数据库案例

//创建老师表
create table teacher(
	id int(10) not null,
    name varchar(30) default null,
    primary key(`id`)
);
insert into teacher(`id`,`name`) values(1,'张老师');
insert into teacher(`id`,`name`) values(2,'夏老师');
//创建学生表
create table student(
	id int(10) not null,
    name varchar(30) default null,
    tid int(10) default null,
    primary key(`id`),
    key `fktid`(`tid`),
    constraint `fktid` foreign key(`tid`)
    references `teacher`(`id`)
);
insert into student(id,name,tid) values (1,'聪聪',1);
insert into student(id,name,tid) values (2,'小垃圾',1);
insert into student(id,name,tid) values (3,'小肚子',1);

//查询所有学生对应的老师
select distinct t.name from teacher t join student s on t.id = s.tid;

select s.name,t.name from student s,teacher t where s.tid = t.id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmULo0ZN-1609828347471)(C:\Users\张聪\AppData\Roaming\Typora\typora-user-images\1609400661473.png)]

多对一(多个学生对应一个老师–association关联属性)
按查询嵌套处理
//实体类中定义了老师属性字段,同时原来的属性不可少,否则会报错属性字段匹配不上
package com.zc.entity;

public class Student {
	int id;
	String name;
	int tid;
	Teacher teacher;
	public Student(int id, String name, int tid, Teacher teacher) {
		super();
		this.id = id;
		this.name = name;
		this.tid = tid;
		this.teacher = teacher;
	}
	public Student(int id, String name, int tid) {
		super();
		this.id = id;
		this.name = name;
		this.tid = tid;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getTid() {
		return tid;
	}
	public void setTid(int tid) {
		this.tid = tid;
	}
	public Teacher getTeacher() {
		return teacher;
	}
	public void setTeacher(Teacher teacher) {
		this.teacher = teacher;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", tid=" + tid + ", teacher=" + teacher + "]";
	}
}


public interface StudentMapper {
	
	public List<Student> getStudents();
}


<?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="com.zc.mapper.StudentMapper">
    <select id="getStudents" resultMap="StudentTeacher">
        select * from student
    </select>
    <!--association关联属性,
		type:表示被转换的对象,本文中本来查询的结果集类型应为Student,即被转换的对象为Student
		property:指的是实体类中定义的转换的属性字段
		column:指的是转换的属性字段对象在多对一中多的表中对应的列名字段--这里指老师在学生表中对应的字			段。
		javaType:指的是property对应的对象类型-->
    <resultMap id="StudentTeacher" type="com.zc.entity.Student">
        <association property="teacher" column="tid" javaType="com.zc.entity.Teacher" 			select="getTeacher">
        </association>
    </resultMap>
    
    <select id="getTeacher" resultType="com.zc.entity.Teacher">
        select * from teacher where id=#{id}   
    </select>
</mapper>

package com.zc.test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;

import com.zc.entity.Student;
import com.zc.mapper.StudentMapper;
import com.zc.util.MybatisUtil;

public class Test01 {
	
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
		List<Student> list = mapper.getStudents();
		for (Student student : list) {
			System.out.println("学生:"+student.getName()+",老师:"+student.getTeacher().getName());
		}
		sqlSession.close();
	}
}
/**
*学生:聪聪,老师:张老师
*学生:小垃圾,老师:张老师
*学生:小肚子,老师:夏老师
*/

按结果集映射
<?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="com.zc.mapper.StudentMapper">
    <select id="getStudents" resultMap="StudentTeacher">
       select s.id sid,t.name tname from student s,teacher t where s.tid = t.id
    </select>
    
     <resultMap id="StudentTeacher" type="com.zc.entity.Student">
        <id property="id" column="sid"></id>
        <association property="teacher" javaType="com.zc.entity.Teacher">
            <result property="name" column="tname"></result>
        </association>
     </resultMap>
</mapper>

sql查询实体类中必须要有与之对应数量类型一直的构造方法

一对多(一个老师对应多个学生)
按查询嵌套处理
//一个老师对应多个学生--老师的实体类中创建学生对象的集合
public class Teacher {
	int id;
	String name;
	List<Student> students;
	public Teacher(int id, String name, List<Student> students) {
		super();
		this.id = id;
		this.name = name;
		this.students = students;
	}
	
	public Teacher(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<Student> getStudents() {
		return students;
	}
	public void setStudents(List<Student> students) {
		this.students = students;
	}
	@Override
	public String toString() {
		return "Teacher [id=" + id + ", name=" + name + ", students=" + students + "]";
	}
}

public interface TeacherMapper {
	Teacher getTeacher(int id);
}

<?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="com.zc.mapper.TeacherMapper">
   <select id="getTeacher" resultMap="TeacherStudent">
        select * from teacher where id=#{id};
   </select>
    <!--type:指的是被转换的对象,这里指老师-->
   <resultMap id="TeacherStudent" type="com.zc.entity.Teacher">
       <!--一对多查询出的集合用collection,其中students对应实体类中的创建的学生集合对象,
		property:指的是在实体类中除了表对应字段属性外,多定义的字段属性
		column:这里个人理解是两个表中关联字段在被转换对象表中对应的列名
      	javaType是用来指定pojo中属性的类型,即实体类中定义属性字段的类型,
		ofType指定的是映射到list集合属性中的对象类型-->
       <collection property="students" column="id" javaType="ArrayList" ofType="com.zc.entity.Student" select="getStudent" >
       </collection>
   </resultMap>
   <select id="getStudent" resultType="com.zc.entity.Student">
     select * from student where tid=#{id}
   </select>
</mapper>

public class Test01 {
	
	public static void main(String[] args) {
		SqlSession sqlSession = MybatisUtil.getSession();
		TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
		Teacher teacher = mapper.getTeacher(1);
		List<Student> list = teacher.getStudents();
		for (Student student : list) {
			System.out.println("老师:"+teacher.getName()+",学生:"+student.getName());
		}
        /**
        *老师:张老师,学生:聪聪
		*老师:张老师,学生:小垃圾
        */
		sqlSession.close();
	}
}

按结果集映射

实体类中必须有与sql查询结果集对应类型、数量的构造方法。如这里查询出sid,sname,tname三个结果字段,那么teacher和student类中也要都有对应的int,string,string构造方法

<?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="com.zc.mapper.TeacherMapper">
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.name tname from teacher t,student s where t.id=s.tid and t.id = #{id} 
    </select>
    <resultMap id="TeacherStudent" type="com.zc.entity.Teacher">
        <result property="name" column="tname"></result>
        <collection property="students" ofType="com.zc.entity.Student">
            <result property="id" column="sid"></result>
            <result property="name" column="sname"></result>
        </collection>
    </resultMap>
</mapper>

七、动态sql
  1. if语句–这样写有个弊端就是当name为null时,语句后面会变为where and position=#{position}

    <?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="com.zc.mapper.HeroMapper">
        <select id="selectHerosIf"  resultType="com.zc.entity.Hero">
            select * from hero where
    	   <if test="name!=null">
    	       name=#{name}
    	   </if>
    	   <if test="position!=null">
    	       and position=#{position}
    	   </if>
        </select>
    </mapper>
    
    
  2. where

    <?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="com.zc.mapper.HeroMapper">
        <select id="selectHerosIf"  resultType="com.zc.entity.Hero">
            select * from hero
           <where>
               <if test="name!=null">
                   name=#{name}
               </if>
               <if test="position!=null">
                   and position=#{position}
               </if>
           </where>
        </select>
    </mapper>
    
    
  3. set

    <?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="com.zc.mapper.HeroMapper"> 
        <update id="updateHero">
            update hero
            <set>
                <if test="name!=null">
                    name=#{name}
                </if>
                <if test="position!=null">
                    position=#{position}
                </if>
            </set>
            <where>
              age=#{age}
            </where>
        </update>
    </mapper>
    
    
  4. choose

    <?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="com.zc.mapper.HeroMapper">
        <select id="seHerosChoose"  resultType="com.zc.entity.Hero">
            select * from hero
            <where>
    	       <choose>
    	         <when test="name!=null">
    	            name=#{name}
    	         </when>
    	         <when test="position!=null">
                    and position=#{position}
                 </when>
                 <when test="age!=null">
                    and age=#{age}
                 </when>
    	       </choose>
            </where>
        </select>
    </mapper>
    
    
  5. Foreach

八、缓存

1、简介

  • 定义:存在内存中的临时数据
  • 为什么使用缓存:减少与数据库交互数据,提高系统效率
  • 什么样数据使用缓存:经常查询且不经常改变的数据

2、mybatis缓存

​ 默认两级缓存:一级缓存、二级缓存

  • 默认情况下只有一级缓存开启–也叫本地缓存,与数据库同一次会话期间查询到的数据会放在本地缓存。是sqlsession级别的缓存,一直开启,我们关闭不了。
  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存–也叫全局缓存
  • mybatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存

3、使用二级缓存步骤–只有当会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

  • 开启全局缓存
<!--mybatis-config.xml中配置-->
<setting name="cacheEnabled" value="true"></setting>

  • 在每一个mapper.xml中配置使用二级缓存
<!--这个配置创建了一个FIFO缓存,每隔60秒刷新,最多可以存储结果对象或列表的512个应用,返回的对象被认为是只读的。-->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true">

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值