框架学习三MyBatis

本文详细介绍了MyBatis的工作原理,包括配置文件、会话工厂、Executor执行器和MappedStatement对象等内容。并逐步讲解了如何搭建MyBatis、实现CRUD操作,以及如何利用ThreadLocal处理sqlSession、配置别名、获取新增数据id和使用log4j显示sql语句。同时,文章涵盖了MyBatis的复杂查询、PageHelper分页、缓存机制、注解使用和Lombok插件的应用,提供了一套完整的MyBatis实践教程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis

MyBatis工作原理

(1)读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息

(2)加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表

(3)构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory

(4)创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法

(5)Executor执行器:MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,通过负责查询缓存的维护

(6)MappedStatement对象:在Executor接口的执行方法中有一个MapppedStatement类型参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id,参数等信息

(7)输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型,输入参数映射过程类似于JDBC对prepareStatement对象设置参数的过程

(8)输出结果映射:输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程
在这里插入图片描述

MyBatis工作流程

(1)SqlSession为主要的调配者,持有Configuration与Executor

(2)先是创建Mapper委托Configuration去以MapperProxy给Mapper接口做动态代理,底层查询方法根据mapper.xml的查询类型执行SqlSession的查询方法

(3)而SqlSession在查询时又委托Executor去做实际的查询,Executor会使用Statement查询结果集

(4)然后使用ResultSetMapping做结果集的映射POJO,然后返回给SqlSession,因为动态代理,所以mapper的方法实际是SqlSession执行的查询方法,所以这时候SqlSession返回给方法查询结果,表面看起来像是Mapper的方法返回的结果,实际上却是SqlSession在做事情

1.搭建Mybatis

1.添加驱动包

<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.40</version>
    </dependency>

2.添加配置文件:src/mybatis-config.xml

设置连接数据库的配置文件的作用:

(1)指定连接数据库的url,username,password、driver

(2)由框架自动获取连接

(3)指定了事务的管理对象

配置文件中default要和id值相同,default表示默认访问环境(可以自己指定使用哪个数据源)

<?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>
<!--    连接数据库的环境,default=“环境的id”-->
    <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/test"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定maper文件的路径(maven项目从resources源文件夹下找资源)-->
    <mappers>
        <mapper resource="StudentMapper.xml"/>
    </mappers>
</configuration>

3.创建实体类和Dao接口

4.设置mapper文件(在mapper文件中配置sql语句)

<?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里面添加sql语句-->
<mapper namespace="com.zhq.dao.StudentDao">
<!--    id="方法名",   结果集自动注入到bean中(因为bean的字段名和列名一致)-->
    <select id="findAll" resultType="com.zhq.bean.Student">
        select * from user
    </select>
</mapper>

5.修改mybatis的配置文件,加入mapper标签,对应mapper配置文件

6.获得SqlSession,通过该对象进行数据操作

 			//1.加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis.xml");
            //2.得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader);
            //3.得到sqlSession对象
            SqlSession session = build.openSession();
            //4.操作sql
            //方法参数是被调取的sql的完整路径=namespace+id
            List<Student> list = session.selectList("com.zhq.dao.StudentDao.findAll");
            for (Student student : list) {
                System.out.println(student);
            }
            //6.关闭资源
            session.close();
            reader.close();

2.Mybatis实现CRUD

方法传入的参数,mapper文件中参数的读取:

(1)单个基本类型参数或String类型:

mapper读取参数:#{参数名(也可以是自定义名称)}

(2)参数类型为对象类型时:

//insert、delete、update、select中的parameterType参数可以省略
#{对象中的属性名}

(3)多个参数时:

将参数封装到map集合中,再将map集合传递给mapper文件

取值的时候用,#{map的key值}

如果处理结果没有和实体类做对应的时候,可以返回map类型

<select id="find" resultType="map"><select>

在做查询时,如果需要将查询的结果和实体类属性自动对应的话,要属性名=列名

添加:session.insert(“namespace+id”,传递给sql的参数值)

修改:session.update(“namespace+id”,传递给sql的参数值)

删除:session.deletet(“namespace+id”,传递给sql的参数值)

单行:session.selectOne(“namespace+id”,传递给sql的参数值)

多行:session.selectList(“namespace+id”,传递给sql的参数值)

处理多个聚合函数(返回结果和实体类没有对应的话):使用map作为方法的返回值,默认key是类名

注意:增删改的时候需要提交事务

查询的时候一定要添加resultType

3.省略Dao实现类

Read read = ResourceAsReader("mybatis.xml");
SqlSession session = new SqlSessionFactoryBuilder().build(read).openSession();
//参数是接口的class类
StudentDao dao = session.getMapper(Student.class);

4.ThreadLocal处理sqlSession

ThreadLocal并不是一个线程的本地实现版本,它并不是一个Thread,而是threadloaclvariable(线程局部变量),可能命名为ThreadLocalVar更合适。线程局部变量功能非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突

演示例子:

public class TestThread {
    private ThreadLocal<String> threadLocal = new ThreadLocal<>();
    private List<String> list = new ArrayList<>();
    class A extends Thread {
        //A线程存储值
        @Override
        public void run() {
            System.out.println("A线程开始存值");
            threadLocal.set("threadlocal存值开始");
            list.add("list存值开始");
            System.out.println("A---------threadLocal里面的值="+threadLocal.get());

        }
    }
    class B extends Thread {
        //B线程获取值
        @Override
        public void run() {
            System.out.println("B线程开始取值");
            String s = threadLocal.get();
            String s1 = list.get(0);
            System.out.println("B--------threadLocal里面的值="+s);
            System.out.println("list里面的值="+s1);
        }
    }

    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        A a = testThread.new A();
        B b = testThread.new B();
        a.start();
        b.start();
    }
}

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiZ808AR-1601890020930)(file:///C:\Users\zhqsocool\AppData\Roaming\Tencent\Users\840587813\QQ\WinTemp\RichOle[303RWY39C$9WYUKNL{14YO.png)]

SessionUtil类:

public class mybatisUtil {
	private static ThreadLocal<SqlSession> threadLcoal = new ThreadLocal<SqlSession>();
	private static SqlSessionFactory SqlSessionFactory;
	/**
	*
	* 加载配置文件
	*/
	static{
		try{
			Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml");
			SqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
		}catch(IOException e){
			e.printStackTrace();
			throw new RuntimeException(e);
        }
	}
	/**
	*
	* 获取SqlSession
	*
	* @return
	*/
	public static SqlSession getSqlSession(){
		//从当前线程获取
		SqlSession sqlSession = threadLcoal.get();
		if(sqlSession == null){
			sqlSession = SqlSessionFactory.openSession();
			//将sqlSession与当前线程绑定
			threadLcoal.set(sqlSession);
		}
		return sqlSession;
	}
	/**
	* 关闭Session
	*/
	public static void closeSqlSession(){
		//从当前线程获取
		SqlSession sqlSession = threadLcoal.get();
		if(sqlSession != null){
			sqlSession.close();
			//清除threadLocal中的值
			threadLcoal.remove();
		}
	}
}

5.给类起别名

<!--    给实体类起别名-->
    <typeAliases>
<!--        <typeAlias type="com.zhq.bean.Student" alias="student"></typeAlias>-->
<!--        指定哪些包的类可以使用别名,默认别名:类名首字母小写(实际使用的时候,全部小写也可以做结果映射)-->
        <package name="com.zhq.bean"/>
    </typeAliases>

6.获得新增数据的id

适用于可以自增的主键列

<insert useGeneratedKeys="true" keyProperty="userid">

7.log4j显示sql语句

log4j日志记录

(如果出现异常,可能是导包重复了,可以试一下把log4j包的版本改为14)

(1)添加jar包和log4j.properties文件

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.5</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.12</version>
</dependency>
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

log4j.properties

log4j.rootLogger=DEBUG, Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

8.Mybatis复杂查询

1.in查询

foreach标签的属性说明:

  • item表示集合中每一个元素进行迭代时的别名,等同于c标签中的var
  • index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,可以不写
  • open表示该语句以什么开始
  • separator表示每次进行迭代之间以什么符号作为分隔符
  • close表示以什么结束
  • collection属性必须指定,List时用list,数组时取array,Map时取map的key值

(1)参数是list存储

<select id="findA" resultType="student">
        select * from user where age in
        <foreach collection="list" item="sid" open="(" close=")" separator=",">
            #{sid}
        </foreach>
    </select>

注意:parameterType的值可以省略

(2)参数是数组

<select id="findB" resultType="student">
        select * from user where age in
        <foreach collection="array" item="sid" open="(" close=")" separator=",">
            #{sid}
        </foreach>
    </select>

(3)参数是Map,嵌套一个list

<select id="findC" resultType="student">
        select * from user where age in
        <foreach collection="ages" item="sid" open="(" close=")" separator=",">
            #{sid}
        </foreach>
    </select>
    
Map传的是key值:
		SqlSession session = SessionUtil.getSession();
        StudentDao2 mapper = session.getMapper(StudentDao2.class);
        Map map = new HashMap();
        List list = new ArrayList();
        list.add(11);
        list.add(34);
        map.put("ages",list);
        List<Student> students = mapper.findC(map);
        for (Student student : students) {
            System.out.println(student);
        }
        SessionUtil.SessionClose();

2.模糊查询

(1)模糊查询+分页

传递多个参数时,使用Map

String sql、StringBuffer sql;//动态sql的保存

(2)动态sql

模糊查询:

 <if test="属性名!=属性值">
	and ename like '${属性名}'
</if>

注意:test属性中读取属性值时直接写属性名

模糊查询读取属性时使用el表达式,${属性名}

除以上位置外,都使用#{属性名},而且多个条件时使用and,or拼接

如果传递过来的是map类型,则test属性中写的是key

如果传递过来的是实体类,则test属性中写的是实体类的属性名**(区分大小写)**

#{}:相当于占位符?

#{id}:其中的id可以表示输入参数的名称,如果是简单类型名称可以任意

${}:表示拼接sql语句,会引起SQL注入,一般情况下不推荐使用

<if test="ename!=null and ename!="">
	and ename like '%${属性名}%'
</if>
或者:
	and ename like "%"#{username}"%"
或者:
	ename like concat(concat('%',#{username}),'%')

3、区间查询

between 开始值 and 结束值

列名 >= 开始时间 and 列名 <= 结束时间

<select id="findF" resultType="student">
        <!--select * from user where age between #{begin} and #{end}-->
        //<![CDATA[ <= ]]> 防止小于号编译
        select * from user where age >= #{begin} and age <![CDATA[ <= ]]> #{end}
    </select>

4.resultMap

(1)处理单表关系

通过给列起别名,让别名=属性名,也可以实现数据对应

resultType = “指定返回值的类型” //当列名和属性名一致时使用

resultMap = “key值” //1.当列名和属性名不一致 2.做多表查询时

mybatis能实现的是单表的自动操作

(因为mybatis是使用反射的,调用方法只要能获取你的实体类的方法类(get、set)就可以了,只要确保方法名等于列名,属性名不一致其实没什么关系)

<resultMap id="rs1" type="com.zhq.bean.Student">
    <!-- 可以手动指定列名和属性名的关系 ,非主键列使用result 标签,主键列使用id 标签-->
		<id property="dept_no" column="deptno"></id>
        <result property="stuId" column="id"></result>
        <result property="stuName" column="name"></result>
    </resultMap>

(2)处理多表关系

两表联查:一对多和多对一

注意:如果是单表查询,select中使用resultType设置返回的类型即可

但是如果是多表联查,那么select查询需要单独使用resultMap标签类进行结构映射

存的是多方的集合,则使用Collection子标签

存的是一方,则使用association子标签

resultType和resultMap属性只能出现一个

一对多:

<resultMap type="" id="自定义名称">
<!--        先描述自身信息,然后描述关联信息,id表述主键列,非主键列使用result描述-->
		<id property="id" column="dept_id" /><!--主键列-->
		<result property="java 属性名" column="列名" />
		<collection property="属性名" ofType="java 类型">
			<id property="属性名" column="列名" />
			<result property="属性名" column="列名" />
		</collection>
</resultMap>

多对一:

<resultMap type="" id="">
	<id property="" column="" />
	<result property="" column="" />
	<association property="" javaType="">
		<id property="" column="" />
		<result property="" column="" />
	</association>
</resultMap>

JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合中的pojo的属性类型

9.pageHelper分页

sql语句只需要查询数据,不实现分页代码

方式1:

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

优缺点:

物理分页每次都要访问数据库,逻辑分页只访问一次(一次取出全部存在内存中,限定每次读取的数量)

物理分页占用内存少,逻辑分页相对较多

物理分页数据每次都是最新的,逻辑分页有可能滞后

rowBounds实现分页:

SqlSession sqlSession = new SqlSessionFactoryBuiler().build(Resources.getResourceAsReader("mybatis.xml"))
						.openSession();
List<User> userList = sqlSession.selectList("com.zhq.dao.UserDao.findAll",
		null, new RowBounds(0,3));	//rowBounds(开始位置,显示条数)
for (User user:userList) {
	System.out.println(user.getUserName());
}

sql语句:

<select id="findall" resultType="com.yhp.bean.Users">
	select * from users
</select>

方式2:使用分页插件

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数

示例:

<select id="findall" resultType="bean.Emp">
	select * from emp
</select>

(1)导入jar包

分页插件:pagehelper.jar

sql解析工具:jsqlparser.jar

<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.1.6</version>
</dependency>

(2)在MyBatis的总体文件中配置插件,放在<environments default="development">

<plugins>
	<!-- PageHelper4.1.6 -->
		<plugin interceptor="com.github.pagehelper.PageHelper">
			<property name="dialect" value="mysql"/>
		</plugin>
</plugins>

注意:插件5.1以后interceptor不同,并且不需要指定数据库名字

<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor">
	</plugin>
</plugins>

(3)在执行查询之前的设置

PageHelper.startPage(当前页,每页条数)

//分页查询(注意事项:设置分页的值一定要在查询之前)
//1.在工具类中指定页码值和显示条数
PageHelper.startPage(2,5);
//2.调取查询的方法,得到结果集
Student student1=new Student();
//student1.setStuname("aa");
// student1.setAddress1("昌平");
List<Student> list=dao.findall(student1);

//3.将list集合封装到PageInfo对象中
PageInfo pageInfo=new PageInfo(list);
List<Student> list2= pageInfo.getList();
//4.得到结果
for (Student student :list2) {
	System.out.println(student.getStuname());
}
System.out.println("每页显示条数:"+pageInfo.getPageSize());
System.out.println("当前页的条数:"+pageInfo.getSize());
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("上一页:"+pageInfo.getPrePage());
System.out.println("下一页:"+pageInfo.getNextPage());
System.out.println("当前页:"+pageInfo.getPageNum());

10.缓存

缓存:

一级缓存:

SqlSession的缓存——>自动开启

二级缓存:

做到从不同的缓存中共享数据

SqlSessionFactory的缓存——>需要手动开启

映射配置文件中的配置

<mapper namespace="接口路径">
	<cache eviction="FIFO"
		flushInterval="60000"
		size="512"
		readOnly="true"/>
</mapper>

参数说明:

eviction:二级缓存中,缓存的对象从缓存中移除的策略,回收策略为先进先出

flushInterval:刷新缓存的事件间隔,单位:毫秒

size:缓存对象的个数

readOnly:是否是只读的

测试:

//不同qlSession,要同一个sqlSessionFactory
SqlSessionFactory factory= new SqlSessionFactoryBuilder()
		.build(Resources.getResourceAsReader("mybatis-config.xml"));
		
SqlSession sqlSession1=factory.openSession();
Student student = sqlSession1.selectOne("com.yhp.dao.StudentDao.findbystuid", 1);
System.out.println(student.getSname());
sqlSession1.close();

System.out.println("===================================");
SqlSession sqlSession2= factory.openSession();
student = sqlSession2.selectOne("com.yhp.dao.StudentDao.findbystuid", 1);
System.out.println(student.getSname());
sqlSession2.close();

cache元素用来开启当前mapper的namespace下的二级缓存,该元素的属性设置如下:

flushInterval:刷新间隔,可以设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段,默认情况下是不设置的,也就是没有刷新间隔,缓存仅仅在调用语句时刷新

size:缓存数目,可以被设置为任意正整数,要记住你的缓存对象数目和你运行环境可用内存资源数目,默认值是1024

readOnly:只读,属性可以被设置为true或false,只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势,可读写的缓存会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false

eviction:回收策略,默认为LRU,有如下几种:

LRU:最近最少使用的策略,移除最长时间不被使用的对象

FIFO:先进先出策略,按对象进入缓存的顺序来移除

SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象

WEAK:软引用策略,更积极地移除基于垃圾回收器状态和弱引用规则的对象

注意:使用二级缓存时,与查询结果映射的java对象必须实现java.io.Serializable接口的序列化和反序列化操作,如果存在父类,其成员都需要实现序列化接口,实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多种多样,不一定在内存,有可能是硬盘或者远程服务器

11.Mybatis注解

在mybatis中可以将sql语句通过注解的方式定义在java中,此时配置文件扫描该注解的位置即可

<mapper class="com.dao.StudentDao"></mapper>

(1)增

@Insert("insert into student(username,password,birthday) values(#{user_name},#{password},#{birthday})")
	@Options(useGeneratedKeys = true,keyProperty = "userid")
	public int insertstu(Student student);

(2)删

@Delete("delete from student where userid=#{userid}")
public int deleteuser(int userid);

(3)改

@Update("update student set username=#{user_name},sex=#{sex} where userid=#{userid}")
public int updateuser(Student stu);

(4)查

@Select("select * from student")
	/* @Results({
			@Result(id = true, property = "id", column = "test_id")
			@Result(column = "username",property = "user_name")
	})*/

注意:多个@Result的时候两侧加大括号{}

(5)把sql语句放在一个类中集中管理

@SelectProvider(type = 自定义sql所在的类.class,method = ”sql定义的方法“)

实例:

@SelectProvider(type = SqlUtil.class, method = “selectMethod”)

@InsertProvider(type = SqlUtil.class, method = “insertMethod”)

@UpdateProvider(type = SqlUtil.class, method = “updateMethod”)

@DeleteProvider(type = SqlUtil.class, method = “deleteMethod”)

//一定要返回字符串
    public String insertMethod(){
        return "insert into student(studentno,stuname,stuage) values(#{stuNo},#{stuName},#{age})";
    }

    public String updateMethod(){
        return "update student set studentno=#{stuNo},stuname=#{stuName} where studentid=#{stuId}";
    }

    public String selectMethod(){
        return "select * from student";
    }

    public String deleteMethod(){
        return "delete from student where studentid = #{sid}";
    }
    
    //传递多个参数是需要拼接字符串,使用StringBuffer(动态sql的一种)
    public String gradestudent(Map map){
		StringBuffer sql=new StringBuffer("select * from student s,grade g where
s.gid=g.gradeid");
		if (map.get("uname")!=null){
			sql.append(" and username like '%"+map.get("uname")+"%'");
		}
		if(map.get("gname")!=null){
			sql.append(" and gradename like '%"+map.get("gname")+"%'");
		}
		return sql.toString();
	}

(6)resultType

@ResultType(Student.class)
public List<Student> findall();

(7)resultMap

@ResultMap("mapper文件中的id名即可")
public List<Student> findall33();

注意:(1)mapper文件中namespace的值要写当前接口的全路径

(2)配置文件中加载接口和mapper.xml二选一

实例:

@Select("select * from student s ,grade g where s.gid=g.cid")
@ResultMap("com.yhp.dao.StudentDao2.a1")
public List<Student> findstu_grade();
//这里的namespace一定是接口的完整路径
<mapper namespace="com.yhp.dao.StudentDao2">
	<resultMap id="a1" type="student">
		<id property="sid" column="sid"></id>
		<result property="sname" column="sname"></result>
		<association property="grade" javaType="grade">
			<id property="cid" column="cid"></id>
			<result property="cname" column="cname"></result>
		</association>
	</resultMap>
</mapper>

配置文件:只需要扫描mapper文件,不需要扫描接口

<mappers>
	<mapper resource="resultMapper.xml"></mapper>
</mappers>

(8)将不同参数绑定,确保传参正确

@Insert("insert into student(sname1,sex) values(#{sname},#{sex})")
@Options(useGeneratedKeys = true,keyProperty = "sid")
public int insertStu(@Param("sname") String name, @Param("sex")String usersex);

注意:在自定义sql的方法中只能使用#{}

(9)开启二级缓存

//该注解定义在方法上,并且需要和@CacheNamespace(定义类的注解)一起使用,并且对象需要实现序列化接口
@Options(useCache = true,
	flushCache = Options.FlushCachePolicy.FALSE, //表示查询时不刷新缓
	timeout = 10000) //表示查询结果缓存10000秒

@CacheNamespace(size = 512):定义在该命名空间内允许使用内置缓存,最大值为512个对象引用,读写默认是开启的,缓存内省刷新时间为默认3600000毫秒,用来修饰接口

(10)动态sql

@Select(" <script>select * from student where 1=1 " +
				" <if test=\"name!=null and name!=''\">" +
					" and username like '%${name}%'" +
				" </if>" +
				" <if test=\"'pass!=null'\">" +
					" and password like '%${pass}%'"+
				" </if></script>")

12.lombok插件

先在idea工具中添加lombok插件

再添加jar包

<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.2</version>
	<scope>provided</scope>
</dependency>

lombok注解:

@Data注解在类上,提供类的所有属性的get和set方法,此外还提供了equals、canEqual、hashCode、toString方法

@Setter:注解在属性上,为属性提供setting方法

@Getter:注解在属性上,为属性提供getting方法

@Log4j:注解在类上,为类提供一个属性名为log的log4j日志对象

@NoArgsConstructor:注解在类上,为类提供一个无参构造方法

@AllArgsConstructor:注解在类上,为类提供一个全参的构造方法

@Cleanup:可以关闭流

@Builder:被注解的类加个构造者模式

@Synchronized:加个同步锁

@SneakyThrows:等同于try/catch捕捉异常

@NonNull:如果给参数加个注解,参数为null会抛出空指针异常

@Value:注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法

@ToString重写toString方法

13.Mybatis自动化

作用:反向生成实体类,接口、mapper.xml

(1)添加jar包:

<dependency>
	<groupId>org.mybatis.generator</groupId>
	<artifactId>mybatis-generator-core</artifactId>
	<version>1.3.5</version>
</dependency>

(2)加载Maven插件:

<build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
                <configuration>
                    <!--配置文件的路径-->
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.5</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

(3)修改配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置生成器 -->
<generatorConfiguration>
    <!--数据库驱动jar -->
    <classPathEntry
            location="E:\Maven\repository\mysql\mysql-connector-java\5.1.40\mysql-connector-java-5.1.40.jar" />
    <context id="MyBatis" targetRuntime="MyBatis3">
        <!--去除注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mytest"
                        userId="root"
                        password="">
        </jdbcConnection>
        <!--生成实体类 指定包名 以及生成的地址 (可以自定义地址,但是路径不存在不会自动创建
        使用Maven生成在target目录下,会自动创建) -->
        <javaModelGenerator targetPackage="com.zhq.bean"
                            targetProject="E:\办公软件\idea\myprogram\mybatistest\src\main\java">
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!--生成SQLmapper文件 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="E:\办公软件\idea\myprogram\mybatistest\src\main\resources">
        </sqlMapGenerator>
        <!--生成Dao文件,生成接口 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.zhq.dao"
                             targetProject="E:\办公软件\idea\myprogram\mybatistest\src\main\java">
        </javaClientGenerator>
        <table tableName="student" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
        <table tableName="grade" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
        <table tableName="role" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
    </context>
</generatorConfiguration>

运行:maven Project选项——>plugins——>点击mybatis-generator-core

注意:运行一次即可,如果运行过程中,未完全成功,则将原来生成的代码删除后,再次运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值