1 什么是MyBatis?
MyBatis 是一款基于ORM[对象关系映射]的、优秀的持久层[数据访问层]框架,对原始的JDBC技术的封装,可以帮助我们快速的连接和访问数据库。
2 为什么要使用MyBatis?
它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
3 什么是ORM?
ORM[对象关系映射]---我们在访问数据库的时候所编写的都是Java程序,Java程序只认识Java对象,而我们所访问的数据库大多数都是关系型数据库,那么这时Java程序要想访问关系型数据库,那么就需要将Java对象转换成关系型数据,才能被数据库认识。这时我们可以认为一个Java类就是关系型数据库中的一张数据表,Java类中的成员变量是数据库表中的一个列,Java类创建的Java对象就是数据库表中的一行记录。
这时将Java对象对应成为数据库表记录的过程就是对象关系映射【ORM】。
ORM的优点:当我们使用Java程序控制Java对象的时候,数据库中的数据表记录会随之变化。
4 MyBatis的工作原理
5 MyBatis中的核心对象
SqlSessionFactory它是mybatis的核心对象,通过这个对象可以获取到与数据库的连接【SqlSession】。同时这个对象中保存着读取到的核心配置文件【mybatis-config.xml】中的信息【1.数据源 2.SQL映射文件】。
SqlSession对象它表示的是与数据库之间的一个连接(会话)。通过SqlSession对象可以对数据库进行CRUD操作。但是SqlSession对象在使用的时候必须指明到底需要执行的是Mapper文件中的哪个SQL。
5.1 SqlSessionFactory如何创建?有什么作用?常用方法?
在mybatis加载完核心配置文件之后,就可以构建出mybatis的核心对象SqlSessionFactory。
SqlSessionFactory用来创建SqlSession
由于SqlSessionFactory是一个接口,所以不能new,需要子类【SqlSessionFactoryBuilder】。
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
5.2 SqlSession如何创建?有什么作用?常用方法?
//1.如何创建?
SqlSession sqlSession = getSessionFactory().openSession();
UserDao userMapper = sqlSession.getMapper(UserDao.class);
通过核心对象SqlSessionFactory获取到与数据库的连接对象SqlSession(专业术语:sql会话)
SqlSession对象可以创建数据访问接口对象,也可以调用数据库操作方法【增删改查】访问数据库。
由此可知,SqlSession对象访问数据库的方法有2中。
1.SqlSession对象调用getMapper(Class)方法得到数据访问接口对象,通过数据访问接口对象调用数据访问接口中操作数据库的方法。
2.SqlSession对象调用insert(),update(),delete(),select(),直接操作数据库数据。
SqlSession对象提供的常用方法:
1.insert(statement, parameter):添加数据的方法
参数1【String】:需要执行的sql映射文件中的sql语句【数据访问接口+抽象方法名称】
参数2【Object】:输入参数。
2.update(statement, parameter):修改数据的方法
参数1【String】:需要执行的sql映射文件中的sql语句【数据访问接口+抽象方法名称】
参数2【Object】:输入参数。
3.selectOne(statement, parameter):查询一个数据的方法
参数1【String】:需要执行的sql映射文件中的sql语句【数据访问接口+抽象方法名称】
参数2【Object】:输入参数。
4.session.selectList(statement):查询所有数据的方法
参数1【String】:需要执行的sql映射文件中的sql语句【数据访问接口+抽象方法名称】
5.delete(statement, parameter):删除数据的方法
参数1【String】:需要执行的sql映射文件中的sql语句【数据访问接口+抽象方法名称】
参数2【Object】:输入参数。
6.getMapper(class):得到数据访问接口对象
参数1【Class】:被获取的数据访问接口的反射对象
7.commit():提交执行
8.close():关闭sqlsession
6 MyBatis相关的配置文件
6.1 MyBatis的核心配置文件
6.1.1 名称
通过情况下MyBatis的核心配置文件的名称是mybatis-config.xml,当然你自己也可以名称。
6.1.2 位置
关于这个文件的位置:
-
普通的Eclipse创建的java工程,一般都保存在src目录下。
-
普通的Eclipse创建的javaWeb工程,一般都保存在src目录下,也可以保存在WEB-INF目录下
-
普通的Eclipse创建的Maven的java工程,一般都保存在src/main/resources目录下。
-
普通的Eclipse创建的Maven的javaWeb工程,一般都保存在src/main/resources目录下,也可以保存在WEB-INF目录下。
例如: <?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="myjdbc.properties"></properties> <!-- 配置mybatis默认的连接数据库的环境 --> <environments default="development"> <environment id="development"> <!-- 配置事物管理器 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源 --> <dataSource type="POOLED"> <property name="driver" value="${mydriver}"/> <property name="url" value="${myurl}"/> <property name="username" value="${myusername}"/> <property name="password" value="${mypassword}"/> </dataSource> </environment> </environments> <!-- 配置MyBatis数据访问接口的SQL映射文件路径 --> <mappers> <!-- 如果SQL映射文件在数据访问接口包中 --> <!-- <package name="com/click369/mybatis/mapper/PersonMapper.xml"/> --> <!-- 如果SQL映射文件在src/main/resources中 --> <mapper resource="PersonMapper.xml"/> </mappers> </configuration>
6.1.3 文件中的配置元素及其属性
1 <configuration>根元素
2 <properties>元素:配置引入其他的资源文件【.properties】,通过提供的resource属性引入
例如:资源文件【.properties】与本配置在同一个文件夹中【resource=”xxxx.properties”】
资源文件【.properties】与本配置不在同一个文件夹中 【resource=”xxxx/xxxx.properties”】
<properties resource="dbconfig.properties"></properties>
<properties resource="config/dbconfig.properties"></properties>
3 <environments>元素:配置mybatis默认的连接数据库的环境
default属性:默认值是development
4 <environment>元素:配置具体的某一个数据库环境,它是<environments>元素的子元素
id属性:默认值是development
5 <transactionManager>元素:配置默认的事务管理器
type属性:配置事物管理器类型
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
6 <dataSource>元素:配置具体数据库链接的元素,是<environment>元素的子元素。
type属性:数据源类型[配置是否使用数据连接池机制管理数据库链接]
UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然一点慢,它对在及时可用连接方面没有性能要求的简单应用程序是一个很好的选择。 不同的数据库在这方面表现也是不一样的,所以对某些数据库来说使用连接池并不重要,这个配置也是理想的。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
JNDI– 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
7 <property>元素:配置数据源
name属性:数据源属性名称
value属性:数据源属性名称对应的取值
8 <mappers>元素:配置Mapper文件的路径
<!-- 如果SQL映射文件在数据访问接口包中 -->
<mapper resource="com/click369/mybatis/mapper/PersonMapper.xml"/>
<!-- 如果SQL映射文件在src/main/resources中 -->
<mapper resource="PersonMapper.xml"/>
6.2 Sql映射文件【Mapper文件】
Sql映射文件,这个文件是用来配置MyBatis执行数据库操作时所需要的sql语言。
6.2.1 名称
Sql映射文件的名称不是随便给的,与数据访问接口的名称相同,以“.xml”结尾。有多少个数据访问接口,那么到时候就要创建多少个Sql映射文件。
6.2.2 位置
Sql映射文件的位置,一般都是放在与数据访问接口相同的包中。需要注意的是在MyBatis核心配置文件中配置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">
<mapper namespace="com.click369.mybatis.mapper.PersonMapper">
<!-- 配置添加数据的sql语句 -->
<insert id="insertPerson" parameterType="com.click369.mybatis.javabean.Person">
insert into t_person values(null,#{pername},#{perage},#{peraddress})
</insert>
<!-- 配置修改数据的sql语句 -->
<update id="updatePerson" parameterType="com.click369.mybatis.javabean.Person">
update t_person set per_name=#{pername},
per_age=#{perage},
per_address=#{peraddress}
where per_id=#{perid}
</update>
<!-- 配置查询的返回值resultMap -->
<resultMap type="com.click369.mybatis.javabean.Person" id="personMap">
<id column="per_id" property="perid"/>
<result column="per_name" property="pername"/>
<result column="per_age" property="perage"/>
<result column="per_address" property="peraddress"/>
</resultMap>
<!-- 配置根据id查询数据的sql语句 -->
<select id="selectPersonById" parameterType="int" resultMap="personMap">
select * from t_person where per_id=#{perid}
</select>
<!-- 配置查询所有数据的sql语句 -->
<select id="selectPerson" resultMap="personMap">
select * from t_person
</select>
<!-- 配置删除数据的sql语句 -->
<delete id="deletePersonById" parameterType="int">
delete from t_person where per_id=#{perid}
</delete>
</mapper>
6.2.3 文件中的配置元素及其属性
1.<mapper>根元素
namespace属性:配置数据访问接口的包名+接口名
2.<insert>元素:配置添加的sql语句
id属性:配置数据访问接口中的用来添加数据的方法名称。
parameterType属性:配置添加参数的类型
3.<update>元素:配置修改的sql语句
id属性:配置数据访问接口中的用来修改数据的方法名称。
parameterType属性:配置添加参数的类型
4.<delete>元素:配置删除的sql语句
id属性:配置数据访问接口中的用来修改数据的方法名称。
parameterType属性:配置添加参数的类型
5.<select>元素:配置查询的sql语句
id属性:配置数据访问接口中的用来修改数据的方法名称。
parameterType属性:配置添加参数的类型
resultMap属性:配置查询的结果类型。【数据库表中的列名称与实体类中的成员变量的名称不同】
resultType属性:配置查询的结果类型。【数据库表中的列名称与实体类中的成员变量的名称相同】
6.<resultMap>元素:配置查询的结果类型的元素【把数据库表中的列名称与实体类中的成员变量的名称映射起来】
id属性:查询的结果类型的名称。
type属性:配置需要映射的java实体类的类名
7.<id>元素:配置的是主键列的映射关系
column属性:配置数据库表的列名。
property属性:配置实体类的成员变量名称。
8.<result>元素:配置除主键之外的其他列
column属性:配置数据库表的列名。
property属性:配置实体类的成员变量名称。
注意:<insert>元素、<update>元素、<delete>元素、<select>元素的id属性是不能重复,意味着数据访问接口中不能出现方法重载的现象。
7 MyBatis的核心配置文件中的typeAliases元素有什么作用?如何配置?如何使用?
typeAliases元素出现在MyBatis的核心配置文件【MyBatis-config.xml】中。
typeAliases元素用来设置实体类的别名【短名称】。方便在sql映射文件中使用这个短名称。
设置方式1:一个类一个别名
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
设置方式2:
设置一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,会使用 Bean 的首字母小写的非限定类名来作为它的别名。
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
通过注解的方式设置别名:
<typeAliases>
<package name="com.click369.javabean"/>
</typeAliases>
例如1:
mybatis-config.xml
<!-- 设置别名 -->
<typeAliases>
<typeAlias type="com.click369.mybatis.javabean.Person" alias="person"/>
</typeAliases>
PersonMapper.xml
<!-- 配置查询的返回值resultMap -->
<resultMap type="person" id="personMap">
<id column="per_id" property="perid" />
<result column="per_name" property="pername"/>
<result column="per_age" property="perage"/>
<result column="per_address" property="peraddress"/>
</resultMap>
<!-- 配置根据id查询数据的sql语句 -->
<select id="selectPersonById" parameterType="int" resultMap="personMap">
select * from t_person where per_id=#{perid}
</select>
例如2:
mybatis-config.xml
<typeAliases>
<package name="com.click369.mybatis.javabean"/>
</typeAliases>
PersonMapper.xml
<!-- 配置查询的返回值resultMap -->
<resultMap type="person/Person" id="personMap">
<id column="per_id" property="perid" />
<result column="per_name" property="pername"/>
<result column="per_age" property="perage"/>
<result column="per_address" property="peraddress"/>
</resultMap>
<!-- 配置根据id查询数据的sql语句 -->
<select id="selectPersonById" parameterType="int" resultMap="personMap">
select * from t_person where per_id=#{perid}
</select>
8 Sql映射文件中的select元素resultType与 resultMap属性的区别?【输出数据就是返回值】
resultType表示的执行完数据库操作之后,返回的结果数据类型。
这个结果可以用三种类型数据来处理:
1、简单类型。例如:string、long、integer、double等
2、pojo类型。例如:Person,User等
3、HashMap类型。
数据库表中的列名称与实体类中的成员变量的名称相同时,一般设置resultType指定返回的结果数据类型。
resultMap表示的执行完数据库操作之后,返回的结果数据类型。
resultMap是mybatis中最重要最强大的元素,使用resultmap可以解决2个问题:
1、JavaBean的属性名和表字段名不一致的问题。
2.完成高级查询。例如:一对一、一对多、多对多。
9 Sql映射文件中的parameterType属性传入参数【insert/update/delete/select元素的输入参数】
parameterType 主要用于传递输入的参数。
传入的参数有三种方式:
1、简单数据类型。例如:string、long、integer、double等
2、pojo(JavaBean)类型。例如:Person、User等
3、HashMap类型。
<!-- 配置添加信息的SQL语句 -->
<insert id="insertUser" parameterType="user">
insert into t_user values(null,#{username},#{userpass},#{userage},#{useraddress})
</insert>
<!-- 配置根据id查询数据的sql语句 -->
<select id="selectUserById" parameterType="int" resultMap="usermap">
select * from t_user where user_id=#{userid}
</select>
<!-- 配置根据条件查询数据的sql语句 -->
<select id="selectUserByWhere" parameterType="hashMap" resultMap="usermap">
select * from t_user where user_name=#{name} and user_pass=#{pass} and user_age=#{age}
</select>
10 #{}和${}的用法
#{} 实现的是sql语句的预处理,之后执行的sql中用?号代替。使用时不需要关注参数的数据类型。mybatis会自动实现数据类型转换,并且可以防止sql注入。
${}实现sql语句的拼接操作,不做数据类型转换,需要自行判断数据类型,不能防止sql注入。
总结:#{}占位符,用于参数传递。${}用于sql拼接
11 什么是动态SQL?为什么使用动态SQL?有哪些动态SQL?如何使用?
动态sql就是(在进行sql操作的时候)动态的根据属性值(所匹配的条件)来拼接数据库执行的sql语句,也就是多次查询或变更操作,根据传入的属性值不同,动态拼接出不同的可执行sql。包含判断为空、循环等;
1、<if>:
if是为了判断传入的值是否符合某种规则,比如是否不为空;
2、<where>:
where标签可以用来做动态拼接查询条件,当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件;
3、<choose><when><otherwise>:
这是一组组合标签,他们的作用类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件;
4、<foreach>:
foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,里面涉及到 item(具体的每一个对象), index(序号), open(开始符), close(结束符), separator(分隔符);
5、<include>:
include可以把大量重复的代码整理起来,当使用的时候直接include即可,减少重复代码的编写;
6、<set>:
适用于更新中,当匹配某个条件后,才会对该字段进行更新操作
7、<trim>:
是一个格式化标签,主要有4个参数:
prefix(前缀);
prefixOverrides(去掉第一个标记);
suffix(后缀);
suffixOverrides(去掉最后一个标记);
动态sql的执行原理:
第一部分:在启动加载解析xml配置文件的时候进行解析,根据关键标签封装成对应的handler处理对象,封装成sqlSource对象存在mappedStatement。
调用流程:
I、SqlSessionFactoryBuilder对builder对象的时候,调用XMLConfigBuilder解析sqlMapConfig.xml配置文件,在解析过程中使用到了私有的mapperElement(XNode parent)方法
II、上面方法中通过构建XMLMapperBuilder,获取到所有的配置mapper配置,
在调用private void configurationElement(XNode context)方法进行解析mapper.xml,通过void buildStatementFromContext(List list, String requiredDatabaseId)方法解析mapper.xml内的每一个标签
III、循环中构建XMLStatementBuilder对象,调用parseStatementNode()方法来封装mappedStatment对象,
IIII、在过程中需要构建sqlSource对象,通过XMLLanguageDriver对象进行处理,在XMLLanguageDriver中构建解析动态标签对象XMLScriptBuilder
第二部分:在执行过程中获取sqlSource中获取bondSql对象时,执行相应的标签handler
调用查询执行到BaseExecutor的query方法时候会去getBoundSql并且将参数传进去,
在sqlSource接口DynamicSqlSource实现类中,调用getBoundSql方法执行过程共创建DynamicContext对象进行判定解析封装成SqlSource对象返回。
12 mybatis的缓存处理?
缓存:提高程序的性能,提高数据的读取速度。现在的互联网时代,几乎所有的网络相关的产品都用到了缓存机制。当然在JavaEE的项目中也有相关的缓存机制。而且不同的框架也有自己的缓存策略。但是真正在开发中,经常会更加稳定成熟的独立的缓存框架(软件),比如:Redis等。
mybatis框架本身也提供相关的缓存机制,并分为两种:1、一级缓存;2、二级缓存。
一级缓存
mybatis默认是开启一级缓存。
当使用openSession方法之后,获取到SqlSession对象,只要使用当前这个SqlSession对象进行数据库的操作,那么执行的是相同的sql(相同的语句和参数),mybatis不进行sql的执行,而是从缓存中找到对应的数据返回。
mybatis的一级缓存:属于SqlSession级别的(会话级别的)。当使用mybatis执行查询时,mybatis会先到一级缓存中找有没有需要查询的数据,如果有就返回,而不会执行sql去数据库中查询。
强制不缓存—openSession(true);【每次去数据库查询数据】
二级缓存
mybatis的二级缓存是当前这个Mapper文件的namespace范围。
也就是同一个namespace下的所有查询语句可以共享二级缓存中的数据。
二级缓存是可以跨越多个session的。只要它们是同一个mapper下的namespace即可。
要开启二级缓存,你需要在你的 SQL 映射(Mapper)文件中添加一行:
二级缓存是在session关闭之前将数据写入到缓存区域,并且要求数据对象必须可序列化。
13 mybatis的高级查询是一对一查询操作有几种方式,每一种如何配置?
一对一
嵌套resultMap:
<!-- 嵌套resultMap 方式1 -->
<resultMap type="userBean" id="userMap">
<id property="userid" column="user_id"/>
<result property="username" column="user_name"/>
<result property="userage" column="user_age"/>
<result property="useraddress" column="user_address"/>
<!-- association 元素配置CardBean对应的 resultMap-->
<association property="cardBean" javaType="cardBean" resultMap="cardMap"></association>
</resultMap>
<resultMap type="cardBean" id="cardMap">
<id property="cardid" column="card_id"/>
<result property="useridfk" column="user_id_fk"/>
<result property="cardcode" column="card_code"/>
<result property="cardyear" column="card_year"/>
</resultMap>
嵌套resultMap:
<!-- 嵌套resultMap 方式2 -->
<resultMap type="userBean" id="userMap1">
<id property="userid" column="user_id"/>
<result property="username" column="user_name"/>
<result property="userage" column="user_age"/>
<result property="useraddress" column="user_address"/>
<!-- association 元素配置CardBean对应的 resultMap-->
<association property="cardBean" javaType="cardBean">
<id property="cardid" column="card_id"/>
<result property="useridfk" column="user_id_fk"/>
<result property="cardcode" column="card_code"/>
<result property="cardyear" column="card_year"/>
</association>
</resultMap>
嵌套select
<mapper namespace="com.click369.mapper.CardBeanMapper">
<!-- 嵌套select -->
<resultMap type="cardBean" id="cardMap">
<id property="cardid" column="card_id"/>
<result property="useridfk" column="user_id_fk"/>
<result property="cardcode" column="card_code"/>
<result property="cardyear" column="card_year"/>
<!-- association配置查询用户基本信息的sql -->
<association property="userBean" column="user_id_fk" javaType="userBean" select="getUserByUseridFk"></association>
</resultMap>
<select id="selectCardUserByCardId" parameterType="int" resultMap="cardMap">
select * from t_card where card_id=#{cardid};
</select>
<resultMap type="userBean" id="userMap">
<id property="userid" column="user_id"/>
<result property="username" column="user_name"/>
<result property="userage" column="user_age"/>
<result property="useraddress" column="user_address"/>
</resultMap>
<select id="getUserByUseridFk" parameterType="int" resultMap="userMap">
select * from t_user where user_id=#{useridfk};
</select>
</mapper>
14 mybatis的高级查询是一对多查询操作有几种方式,每一种如何配置?
一对多:
嵌套resultMap:
<mapper namespace="com.click369.mapper.ClassBeanMapper">
<!-- 嵌套resultMap 方式1 -->
<resultMap type="classBean" id="classMap">
<id property="classid" column="class_id"/>
<result property="classcode" column="class_code"/>
<result property="classname" column="class_name"/>
<!-- collection元素配置一对多 -->
<collection property="studentList" ofType="studentBean" resultMap="studentMap"></collection>
</resultMap>
<resultMap type="studentBean" id="studentMap">
<id property="stuid" column="stu_id"/>
<result property="classidfk" column="class_id_fk"/>
<result property="stuname" column="stu_name"/>
<result property="stuage" column="stu_age"/>
<result property="stuaddress" column="stu_address"/>
</resultMap>
<select id="selectClassStudentByClassId" parameterType="java.lang.String" resultMap="classMap">
select c.class_id,c.class_code,c.class_name,
s.stu_id,s.class_id_fk,s.stu_name,s.stu_age,s.stu_address
from t_class as c left outer join t_student as s
on c.class_code=#{classcode};
</select>
</mapper>
嵌套resultMap:
<!-- 嵌套resultMap 方式2 -->
<resultMap type="classBean" id="classMap2">
<id property="classid" column="class_id"/>
<result property="classcode" column="class_code"/>
<result property="classname" column="class_name"/>
<!-- collection元素配置一对多 -->
<collection property="studentList" ofType="studentBean" >
<id property="stuid" column="stu_id"/>
<result property="classidfk" column="class_id_fk"/>
<result property="stuname" column="stu_name"/>
<result property="stuage" column="stu_age"/>
<result property="stuaddress" column="stu_address"/>
</collection>
</resultMap>
<select id="selectClassStudentByClassId2" parameterType="java.lang.String" resultMap="classMap2">
select c.class_id,c.class_code,c.class_name,
s.stu_id,s.class_id_fk,s.stu_name,s.stu_age,s.stu_address
from t_class as c left outer join t_student as s
on c.class_code=#{classcode};
</select>
嵌套select:
<!-- 嵌套select -->
<resultMap type="classBean" id="classMap3">
<id property="classid" column="class_id"/>
<result property="classcode" column="class_code"/>
<result property="classname" column="class_name"/>
<collection property="studentList" column="class_id" ofType="studentBean" select="getStudentInfo"></collection>
</resultMap>
<select id="selectClassStudentByClassId3" parameterType="java.lang.String" resultMap="classMap3">
select * from t_class where class_code=#{classcode}
</select>
<resultMap type="studentBean" id="studentMap3">
<id property="stuid" column="stu_id"/>
<result property="classidfk" column="class_id_fk"/>
<result property="stuname" column="stu_name"/>
<result property="stuage" column="stu_age"/>
<result property="stuaddress" column="stu_address"/>
</resultMap>
<select id="getStudentInfo" parameterType="int" resultMap="studentMap3">
select * from t_student where class_id_fk=#{classid}
</select>
15 mybatis的高级查询是多对多查询操作如何配置?
<mapper namespace="com.click369.mapper.RoleBeanMapper">
<resultMap type="roleBean" id="roleMap">
<id property="roleid" column="role_id"/>
<result property="rolename" column="role_name"/>
<result property="roleinfo" column="role_info"/>
<collection property="grouplist" ofType="groupBean" resultMap="groupMap"></collection>
</resultMap>
<resultMap type="groupBean" id="groupMap">
<id property="groupid" column="group_id"/>
<result property="groupname" column="group_name"/>
<result property="groupinfo" column="group_info"/>
</resultMap>
<select id="selectRoleAndGroupByRoleid" parameterType="int" resultMap="roleMap">
select r.role_id,r.role_name,r.role_info,
g.group_id,g.group_name,g.group_info
from t_role as r inner join t_role_group as rg
on r.role_id = rg.role_id_fk
inner join t_group as g
on g.group_id = rg.group_id_fk
where r.role_id=#{roleid}
</select>
</mapper>
16 MyBatis提供的分页查询原理?
mybatis中提供的插件(plugin)机制,运行在mybatis的原有的处理逻辑上添加一些额外的逻辑,这样既不需要修改原来的代码,而且还可以非常容易进行实现。
mybatis的插件机制,本质就拦截指定的查询操作,然后在查询的操作添加相关的逻辑。
使用PageHelper实现分页
1.添加分页插件的依赖
<!-- 配置分页依赖 -->
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2.在MyBatis的核心配置文件中配置插件
<!-- 配置分页插件的拦截器 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 配置方言,使用的是那个库 ,在PageHelper5.0之后 不需要配置-->
<!-- <property name="dialect" value="mysql"/> -->
</plugin>
</plugins>
3.数据库访问接口
package com.click369.mapper;
import java.util.List;
import com.click369.javabean.PersonBean;
public interface PersonBeanMapper {
boolean insertPerson(List<PersonBean> personlist);
//分页查询
List<PersonBean> findPage();
}
4.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="com.click369.mapper.PersonBeanMapper">
<insert id="insertPerson" parameterType="list">
insert into t_person values
<foreach collection="list" item="person" separator=",">
(null,#{person.personname},#{person.personage},#{person.personaddress})
</foreach>
</insert>
<resultMap type="PersonBean" id="personMap">
<id property="personid" column="person_id"/>
<result property="personname" column="person_name"/>
<result property="personage" column="person_age"/>
<result property="personaddress" column="person_address"/>
</resultMap>
<select id="findPage" resultMap="personMap">
select * from t_person
</select>
</mapper>
5.测试分页查询
package test1;
import java.io.InputStream;
import java.util.List;
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 com.click369.javabean.PersonBean;
import com.click369.mapper.PersonBeanMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
public class TestMain {
public static void main(String[] args) {
try{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=factory.openSession();
PersonBeanMapper personMapper=session.getMapper(PersonBeanMapper.class);
//使用pageHelper插件的startPage()方法
//设置分页的起始页码和每页的显示数据的行数
PageHelper.startPage(10,10);
List<PersonBean> personlist=personMapper.findPage();
//将查询结果封装得到PageInfo类
PageInfo<PersonBean> personBeanPageInfo=new PageInfo<PersonBean>(personlist);
session.commit();
session.close();
System.out.println("当前页=="+personBeanPageInfo.getPageNum());
System.out.println("每页数量=="+personBeanPageInfo.getPageSize());
System.out.println("当前页的数量=="+personBeanPageInfo.getSize());
System.out.println("总记录数=="+personBeanPageInfo.getTotal());
System.out.println("总页数=="+personBeanPageInfo.getPages());
//得到当前页的结果集合
List<PersonBean> perlist=personBeanPageInfo.getList();
for(PersonBean per:perlist){
System.out.println(per.getPersonid()+" "+per.getPersonname());
}
}catch(Exception e){
e.printStackTrace();
}
}
}