1.什么是MyBatis?
mybatis是一个基于ORM(对象关系映射)的持久层数据访问框架。
2.为什么要使用MyBatis?
MyBatis 是一款优秀的持久层[数据访问层]框架,对原始的JDBC技术的封装,可以帮助我们快速的链接和访问数据库。
优点:它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
3.什么是ORM?
ORE就是对象关系映射---Java对象对应成为数据库表记录的过程就是对象关系映射。
ORM的优点:当我们使用Java程序控制Java对象的时候,数据库中的数据表记录会随之变化。
4.MyBatis的工作原理
5.MyBatis中的核心对象
SqlSessionFactory如何创建?有什么作用?常用方法?
它是mybatis的核心对象,通过这个对象可以获取到与数据库的连接【SqlSession】。同时这个对象中保存着读取到的核心配置文件【mybatis-config.xml】中的信息【1.数据源 2.SQL映射文件】
例如:
加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession如何创建?有什么作用?常用方法?
SqlSession对象它表示的是与数据库之间的一个连接(会话)。
通过SqlSession对象可以对数据库进行CRUD操作。
但是SqlSession对象在使用的时候必须指明到底需要执行的是Mapper文件中的哪个SQL。
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
package com.click369.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 org.junit.Test;
import com.click369.mybatis.javabean.Person;
import com.click369.mybatis.mapper.PersonMapper;
public class MyTest2 {
/**
* 测试添加
*/
@Test
public void testInsertPerson(){
SqlSession session=null;
try{
//加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession接口对象【有增删该查方法】
session=sqlSessionFactory.openSession();
Person person=new Person();
person.setPername("zhangsan");
person.setPerage(23);
person.setPeraddress("西安");
int temp=session.insert("com.click369.mybatis.mapper.PersonMapper.insertPerson", person);
System.out.println("temp="+temp);
//提交执行
session.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
/**
* 测试修改
*/
@Test
public void testUpdatePerson(){
SqlSession session=null;
try{
//加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession接口对象【有增删该查方法】
session=sqlSessionFactory.openSession();
Person person=new Person();
person.setPerid(1);
person.setPername("lisi");
person.setPerage(23);
person.setPeraddress("西安");
int temp=session.update("com.click369.mybatis.mapper.PersonMapper.updatePerson", person);
System.out.println("temp="+temp);
//提交执行
session.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
/**
* 测试根据id查询
*/
@Test
public void testSelectPersonById(){
SqlSession session=null;
try{
//加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession接口对象【有增删该查方法】
session=sqlSessionFactory.openSession();
Person person=session.selectOne("com.click369.mybatis.mapper.PersonMapper.selectPersonById", 1);
System.out.println("person.name="+person.getPername());
//提交执行
session.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
/**
* 测试查询所有
*/
@Test
public void testSelectPerson(){
SqlSession session=null;
try{
//加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession接口对象【有增删该查方法】
session=sqlSessionFactory.openSession();
List<Person> personList=session.selectList("com.click369.mybatis.mapper.PersonMapper.selectPerson");
System.out.println("personList.size="+personList.size());
//提交执行
session.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
/**
* 测试根据id删除
*/
@Test
public void testDeletePersonById(){
SqlSession session=null;
try{
//加载mybatis配置文件
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory接口对象
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession接口对象【有增删该查方法】
session=sqlSessionFactory.openSession();
int temp=session.delete("com.click369.mybatis.mapper.PersonMapper.deletePersonById", 1);
System.out.println("temp="+temp);
//提交执行
session.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
}
6.MyBatis相关的配置文件
MyBatis的核心配置文件
1.名称
通常情况下 mybtis-config.xml,也可以自己命名
2.位置
- 普通的Eclipse创建的java工程,一般都保存在src目录下。
- 普通的Eclipse创建的javaWeb工程,一般都保存在src目录下,也可以保存在WEB-INF目录下
- 普通的Eclipse创建的Maven的java工程,一般都保存在src/main/resources目录下。
- 普通的Eclipse创建的Maven的javaWeb工程,一般都保存在src/main/resources目录下,也可以保存在WEB-INF目录下。
3.文件中的配置元素及其属性
配置元素:
<configuration>,<properties>,<environments>,<environment>,<transactionManager>,<dataSource>,<property>, <mappers>等等。
1.<properties>元素:配置引入其他的资源文件【.properties】,通过提供的resource属性引入
2.<environments>元素:配置mybatis默认的连接数据库的环境
default属性:默认值是development
3.<environment>元素:配置具体的某一个数据库环境,它是<environments>元素的子元素
id属性:默认值是development.
4.<transactionManager>元素:配置默认的事务管理器
type属性:配置事物管理器类型
- JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
-
例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager><dataSource>元素:配置具体数据库链接的元素,是<environment>元素的子元素。
5.type属性:数据源类型[配置是否使用数据连接池机制管理数据库链接]
6.<property>元素:配置数据源
name属性:数据源属性名称
value属性:数据源属性名称对应的取值
7.<mappers>元素:配置Mapper文件的路径
<!-- 如果SQL映射文件在数据访问接口包中 -->
<mapper resource="com/click369/mybatis/mapper/PersonMapper.xml"/>
<!-- 如果SQL映射文件在src/main/resources中 -->
<mapper resource="PersonMapper.xml"/>
Sql映射文件【Mapper文件】
1.名称
与数据访问接口的名称相同,以“.xml”结尾
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>
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表示的执行完数据库操作之后,返回的结果数据类型。
这个结果可以用三种类型数据来处理:
- 简单类型。例如:string、long、integer、double等
- pojo类型。例如:Person,User等
- HashMap类型。
数据库表中的列名称与实体类中的成员变量的名称相同时,一般设置resultType指定返回的结果数据类型。
create table t_student(
stuid int primary key auto_increment,
stuname varchar(20),
stuage int,
stuaddress varchar(30)
);
package com.click369.mybatis.javabean;
import java.io.Serializable;
/**
* 保存学生信息的java实体类
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class Student implements Serializable{
private int stuid;
private String stuname;
private int stuage;
private String stuaddress;
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
public String getStuaddress() {
return stuaddress;
}
public void setStuaddress(String stuaddress) {
this.stuaddress = stuaddress;
}
}
package com.click369.mybatis.mapper;
import java.util.List;
import com.click369.mybatis.javabean.Student;
/**
* Student信息的数据访问接口
* 注意:数据库操作方法是不能有重载,后面配置MyBatisSQL映射文件的时候需要使用这个方法名称
* @author Administrator
*
*/
public interface StudentMapper {
boolean insertStudent(Student student);
List<Student> selectStudent();
}
<?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="testconfig/myjdbc.properties"></properties>
<typeAliases>
<package name="com.click369.mybatis.javabean"/>
</typeAliases>
<!-- 配置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>
<mapper resource="com/click369/mybatis/mapper/PersonMapper.xml"/>
<mapper resource="com/click369/mybatis/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
<?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.StudentMapper">
<!-- 配置添加信息的SQL语句 -->
<insert id="insertStudent" parameterType="Student">
insert into t_student values(null,#{stuname},#{stuage},#{stuaddress})
</insert>
<!-- 配置根据id查询数据的sql语句 -->
<select id="selectStudent" resultType="Student">
select * from t_student
</select>
</mapper>
resultMap表示的执行完数据库操作之后,返回的结果数据类型。
resultMap是mybatis中最重要最强大的元素,使用resultmap可以解决2个问题:
- JavaBean的属性名和表字段名不一致的问题。
create table t_person(
per_id int primary key auto_increment,
per_name varchar(20),
per_age int,
per_address varchar(30)
);
package com.click369.mybatis.javabean;
import java.io.Serializable;
/**
* 保存个人信息的java实体类
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class Person implements Serializable{
private int perid;
private String pername;
private int perage;
private String peraddress;
public int getPerid() {
return perid;
}
public void setPerid(int perid) {
this.perid = perid;
}
public String getPername() {
return pername;
}
public void setPername(String pername) {
this.pername = pername;
}
public int getPerage() {
return perage;
}
public void setPerage(int perage) {
this.perage = perage;
}
public String getPeraddress() {
return peraddress;
}
public void setPeraddress(String peraddress) {
this.peraddress = peraddress;
}
}
package com.click369.mybatis.mapper;
import java.util.List;
import com.click369.mybatis.javabean.Person;
/**
* Person信息的数据访问接口
* 注意:数据库操作方法是不能有重载,后面配置MyBatisSQL映射文件的时候需要使用这个方法名称
* @author Administrator
*
*/
public interface PersonMapper {
/**
* 添加数据
* @param person
* @return
*/
boolean insertPerson(Person person);
/**
* 修改数据
* @param person
* @return
*/
boolean updatePerson(Person person);
/**
* 删除数据
* @param person
* @return
*/
boolean deletePersonById(int perid);
/**
* 根据id查询数据
* @param person
* @return
*/
Person selectPersonById(int perid);
/**
* 查询所有数据
* @param person
* @return
*/
List<Person> selectPerson();
}
<?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="testconfig/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"/> -->
<package name="com/click369/mybatis/mapper"/>
<!-- 如果SQL映射文件在src/main/resources中 -->
<!-- <mapper resource="PersonMapper.xml"/>-->
<!-- <mapper resource="com/click369/mybatis/mapper/PersonMapper.xml"/>-->
</mappers>
</configuration>
<?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" resultType="" resultMap="personMap">
select * from t_person
</select>
<!-- 配置删除数据的sql语句 -->
<delete id="deletePersonById" parameterType="int">
delete from t_person where per_id=#{perid}
</delete>
</mapper>
2.完成高级查询。例如:一对一、一对多、多对多。
9.Sql映射文件中的parameterType属性传入参数
【insert/update/delete/select元素的输入参数】
1.#{}和${}的用法
在mybatis的mapper文件中,参数传递有2种方式。一种是#{},另一种是${},两者有较大的区别:
#{} 实现的是sql语句的预处理,之后执行的sql中用?号代替。使用时不需要关注参数的数据类型。mybatis会自动实现数据类型转换,并且可以防止sql注入。
${}实现sql语句的拼接操作,不做数据类型转换,需要自行判断数据类型,不能防止sql注入。
总结:#{}占位符,用于参数传递。${}用于sql拼接
2.什么是动态SQL?为什么使用动态SQL?有哪些动态SQL?如何使用?
MyBatis 的强大特性之一便是它的动态 SQL。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
- if
- choose (when, otherwise)
- trim (where, set)
- Foreach
测试if 元素
需求:查询用户信息,如果输入了用户名,根据用户名进行模糊查找,如果没有用户名/用户名为空,那么就查询所有。
//测试if这个sql元素
List<PersonBean> selectPersonTestIf(@Param("name")String name);
<select id="selectPersonTestIf" resultType="PersonBean">
select * from t_person where 1=1
<if test="name != null and name !=''">
and per_name like #{name}
</if>
</select>
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
List<PersonBean> personlist=mapper.selectPersonTestIf("%test%");
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3327bd23]
==> Preparing: select * from t_person where 1=1 and per_name like ?
==> Parameters: %test%(String)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 3, testvalue, 23, java
<== Row: 7, testmap, 4, java
<== Total: 2
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
List<PersonBean> personlist=mapper.selectPersonTestIf(null);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@544fe44c]
==> Preparing: select * from t_person where 1=1
==> Parameters:
<== Columns: per_id, per_name, per_age, per_address
<== Row: 3, testvalue, 23, java
<== Row: 4, zhangsan, 23, java
<== Row: 5, lisi, 23, java
<== Row: 6, wangwu, 23, java
<== Row: 7, testmap, 4, java
<== Row: 8, sssss, 23, dddddd
<== Row: 9, wwwww, 23, rrrrrrr
<== Total: 7
测试choose (when, otherwise)元素【每次只匹配一个条件】
需求:查询用户信息,如果输入了用户名,根据用户名进行模糊查找,
如果输入了年龄,根据年龄进行匹配查找,
如果输入了地址,根据地址进行模糊查找,
如果查询条件都为空,那么就查询所有。
有点类似于Switch语句
例如:
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
PersonBean person=new PersonBean();
person.setPer_name("%test%");
List<PersonBean> personlist=mapper.selectPersonTestChoose1(person);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3327bd23]
==> Preparing: select * from t_person where 1=1 and per_name like ?
==> Parameters: %test%(String)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 3, testvalue, 23, java
<== Row: 7, testmap, 4, java
<== Total: 2
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
PersonBean person=new PersonBean();
person.setPer_age(4);
List<PersonBean> personlist=mapper.selectPersonTestChoose1(person);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@52a86356]
==> Preparing: select * from t_person where 1=1 and per_age = ?
==> Parameters: 4(Integer)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 7, testmap, 4, java
<== Total: 1
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
PersonBean person=new PersonBean();
person.setPer_name("%test%");
person.setPer_age(4);
List<PersonBean> personlist=mapper.selectPersonTestChoose1(person);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3327bd23]
==> Preparing: select * from t_person where 1=1 and per_name like ?
==> Parameters: %test%(String)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 3, testvalue, 23, java
<== Row: 7, testmap, 4, java
<== Total: 2
//测试if这个sql元素
List<PersonBean> selectPersonTestIf2(PersonBean person);
<select id="selectPersonTestIf2" parameterType="PersonBean" resultType="PersonBean">
select * from t_person where 1=1
<if test="per_name != null and per_name !=''">
and per_name like #{per_name}
</if>
<if test="per_age != null and per_age != 0">
and per_age = #{per_age}
</if>
</select>
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
PersonBean person=new PersonBean();
person.setPer_name("%test%");
person.setPer_age(4);
List<PersonBean> personlist=mapper.selectPersonTestIf2(person);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@21213b92]
==> Preparing: select * from t_person where 1=1 and per_name like ? and per_age = ?
==> Parameters: %test%(String), 4(Integer)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 7, testmap, 4, java
<== Total: 1
测试where元素
需求:根据用户名和年龄还有地址进行组合条件查询
//测试Where这个sql元素
List<PersonBean> selectPersonTestWhere1(PersonBean person);
<select id="selectPersonTestWhere1" parameterType="PersonBean" resultType="PersonBean">
select * from t_person
<where>
<if test="per_name != null and per_name !=''">
and per_name like #{per_name}
</if>
<if test="per_age != null and per_age != 0">
and per_age = #{per_age}
</if>
</where>
</select>
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
PersonBean person=new PersonBean();
person.setPer_name("%test%");
person.setPer_age(4);
List<PersonBean> personlist=mapper.selectPersonTestWhere1(person);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ce81285]
==> Preparing: select * from t_person WHERE per_name like ? and per_age = ?
==> Parameters: %test%(String), 4(Integer)
<== Columns: per_id, per_name, per_age, per_address
<== Row: 7, testmap, 4, java
<== Total: 1
测试set元素
需求:修改用户的信息
//测试Where这个sql元素
boolean updateTestSet1(PersonBean person);
<update id="updateTestSet1" parameterType="PersonBean" >
update t_person
<set>
<if test="per_name !=null and per_name !=''">
per_name = #{per_name},
</if>
<if test="per_age !=null and per_age !=0">
per_age = #{per_age},
</if>
<if test="per_address !=null and per_address !=''">
per_address = #{per_address},
</if>
</set>
<where>per_id = #{per_id}</where>
</update>
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4e1d422d]
==> Preparing: update t_person SET per_name = ? WHERE per_id = ?
==> Parameters: hhhhh(String), 8(Integer)
<== Updates: 1
测试foreach 元素
需要:删除指定id的数据元素
//测试foreach 这个sql元素
boolean deleteTestForeach(List<Integer> ids);
<!-- 批量删除 -->
<delete id="deleteTestForeach" parameterType="java.util.List">
delete from t_person where per_id in
<foreach collection="list" item="personid" open="(" close=")" separator=",">
#{personid}
</foreach>
</delete>
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
List<Integer> ids=new ArrayList<Integer>();
ids.add(4);
ids.add(7);
boolean flag=mapper.deleteTestForeach(ids);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@31610302]
==> Preparing: delete from t_person where per_id in ( ? , ? )
==> Parameters: 4(Integer), 7(Integer)
<== Updates: 2
批量添加的配置操作。
//测试foreach 这个sql元素
boolean insertTestForeach(List<PersonBean> personlist);
<!-- 批量添加-->
<insert id="insertTestForeach" parameterType="java.util.List">
insert into t_person values
<foreach collection="list" item="person" separator=",">
(null,#{person.per_name},#{person.per_age},#{person.per_address})
</foreach>
</insert>
PersonBeanMapper mapper=session.getMapper(PersonBeanMapper.class);
List<PersonBean> personlist=new ArrayList<PersonBean>();
PersonBean person1=new PersonBean();
person1.setPer_name("qqqqq");
person1.setPer_age(2);
person1.setPer_address("wwwww");
PersonBean person2=new PersonBean();
person2.setPer_name("eeeee");
person2.setPer_age(4);
person2.setPer_address("rrrrr");
PersonBean person3=new PersonBean();
person3.setPer_name("ttttt");
person3.setPer_age(45);
person3.setPer_address("yyyyy");
personlist.add(person1);
personlist.add(person2);
personlist.add(person3);
boolean flag=mapper.insertTestForeach(personlist);
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@31610302]
==> Preparing: insert into t_person values (null,?,?,?) , (null,?,?,?) , (null,?,?,?)
==> Parameters: qqqqq(String), 2(Integer), wwwww(String), eeeee(String), 4(Integer), rrrrr(String), ttttt(String), 45(Integer), yyyyy(String)
1.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)文件中添加一行:<cache/>
二级缓存是在session关闭之前将数据写入到缓存区域,并且要求数据对象必须可序列化。
mybatis高级缓存
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。
可用的收回策略有:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。
2.mybatis的高级查询是一对一查询操作有几种方式,每一种如何配置?、
需求:查询指定用户信息。
分析:可以将用户的信息保存在两张表中,第一张表保存用户的基本信息,第二张表保存用户的身份证信息,这时用户的基本信息与用户的身份证信息就是一组一对一的信息。
#用户基本信息表
create table t_user(
user_id int primary key auto_increment,
user_name varchar(20),
user_age int,
user_address varchar(30)
);
#用户身份证信息表
create table t_card(
card_id int primary key auto_increment,
user_id_fk int not null unique,
card_code varchar(20),
card_year int
);
ALTER TABLE t_card ADD CONSTRAINT user_id_fk FOREIGN KEY(user_id_fk) REFERENCES t_user(user_id);
insert into t_user values(null,'zhangsan',23,'西安');
insert into t_card values(null,1,'111111111',20);
package com.click369.javabean;
import java.io.Serializable;
/**
* 保存用户基本信息java实体类
* 由于当我们在查询用户基本信息的时候需要连同用户身份证信息一起得到,
* 所以我们就需要在保存用户基本信息的java实体类中新增一个成员变量,用来保存用户身份证信息。
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class UserBean implements Serializable{
private int userid;
private String username;
private int userage;
private String useraddress;
//用来保存用户身份证信息成员变量
private CardBean cardBean;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserage() {
return userage;
}
public void setUserage(int userage) {
this.userage = userage;
}
public String getUseraddress() {
return useraddress;
}
public void setUseraddress(String useraddress) {
this.useraddress = useraddress;
}
public CardBean getCardBean() {
return cardBean;
}
public void setCardBean(CardBean cardBean) {
this.cardBean = cardBean;
}
}
package com.click369.javabean;
import java.io.Serializable;
/**
* 保存用户身份证信息的java实体类
* 由于当我们在查询用户身份证信息的时候需要连同用户基本信息一起得到,
* 所以我们就需要在保存用户身份证信息的java实体类中新增一个成员变量,用来保存用户基本信息。
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class CardBean implements Serializable{
private int cardid;
private int useridfk;
private String cardcode;
private int cardyear;
private UserBean userBean;
public int getCardid() {
return cardid;
}
public void setCardid(int cardid) {
this.cardid = cardid;
}
public int getUseridfk() {
return useridfk;
}
public void setUseridfk(int useridfk) {
this.useridfk = useridfk;
}
public String getCardcode() {
return cardcode;
}
public void setCardcode(String cardcode) {
this.cardcode = cardcode;
}
public int getCardyear() {
return cardyear;
}
public void setCardyear(int cardyear) {
this.cardyear = cardyear;
}
public UserBean getUserBean() {
return userBean;
}
public void setUserBean(UserBean userBean) {
this.userBean = userBean;
}
}
嵌套resultMap
package com.click369.mapper;
import com.click369.javabean.UserBean;
/**
* 用户基本信息的数据访问接口
* @author Administrator
*
*/
public interface UserBeanMapper {
//根据用户id得到用户的基本信息和该用户对应的身份证信息
UserBean selectUserCardByUserId(int userid);
}
<?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.UserBeanMapper">
<!-- 嵌套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>
<select id="selectUserCardByUserId" parameterType="int" resultMap="userMap">
select u.user_id,u.user_name,u.user_age,u.user_address,
c.card_id,c.user_id_fk,c.card_code,c.card_year
from t_user as u inner join t_card as c
on u.user_id=c.user_id_fk
where u.user_id=#{userid}
</select>
</mapper>
UserBeanMapper userMapper=session.getMapper(UserBeanMapper.class);
UserBean user=userMapper.selectUserCardByUserId(1);
session.commit();
if(user!=null){
System.out.println(user.getUsername()+"----"+user.getCardBean().getCardcode());
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==>Preparing:select u.user_id,u.user_name,u.user_age,u.user_address, c.card_id,c.user_id_fk,c.card_code,c.card_year from t_user as u inner join t_card as c on u.user_id=c.user_id_fk where u.user_id=?
==> Parameters: 1(Integer)
<== Columns: user_id, user_name, user_age, user_address, card_id, user_id_fk, card_code, card_year
<== Row: 1, zhangsan, 23, 西安, 1, 1, 111111111, 20
<== Total: 1
zhangsan----111111111
//根据用户id得到用户的基本信息和该用户对应的身份证信息
UserBean selectUserCardByUserId1(int userid);
<!-- 嵌套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 id="selectUserCardByUserId1" parameterType="int" resultMap="userMap1">
select u.user_id,u.user_name,u.user_age,u.user_address,
c.card_id,c.user_id_fk,c.card_code,c.card_year
from t_user as u inner join t_card as c
on u.user_id=c.user_id_fk
where u.user_id=#{userid}
</select>
UserBeanMapper userMapper=session.getMapper(UserBeanMapper.class);
UserBean user=userMapper.selectUserCardByUserId1(1);
session.commit();
if(user!=null){
System.out.println(user.getUsername()+"----"+user.getCardBean().getCardcode());
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==> Preparing: select u.user_id,u.user_name,u.user_age,u.user_address, c.card_id,c.user_id_fk,c.card_code,c.card_year from t_user as u inner join t_card as c on u.user_id=c.user_id_fk where u.user_id=?
==> Parameters: 1(Integer)
<== Columns: user_id, user_name, user_age, user_address, card_id, user_id_fk, card_code, card_year
<== Row: 1, zhangsan, 23, 西安, 1, 1, 111111111, 20
<== Total: 1
zhangsan----111111111
嵌套select
package com.click369.mapper;
import com.click369.javabean.CardBean;
/**
* 用户身份证信息数据访问接口
* @author Administrator
*
*/
public interface CardBeanMapper {
//根据用户身份证信息id得到用户的身份证信息和该用户的基本信息
CardBean selectCardUserByCardId(int cardid);
}
<?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.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>
CardBeanMapper cardMapper=session.getMapper(CardBeanMapper.class);
CardBean card=cardMapper.selectCardUserByCardId(1);
session.commit();
if(card!=null){
System.out.println(card.getUserBean().getUsername()+"----"+card.getCardcode());
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
==> Preparing: select * from t_card where card_id=?;
==> Parameters: 1(Integer)
<== Columns: card_id, user_id_fk, card_code, card_year
<== Row: 1, 1, 111111111, 20
====> Preparing: select * from t_user where user_id=?;
====> Parameters: 1(Integer)
<==== Columns: user_id, user_name, user_age, user_address
<==== Row: 1, zhangsan, 23, 西安
<==== Total: 1
<== Total: 1
zhangsan----111111111
2.mybatis的高级查询是一对多查询操作有几种方式,每一种如何配置?
需求:根据班级编号查询班级信息
分析:我们需要准备2张数据库表,第一张数据库表是保存班级信息的,第二张表是保存这个班级中的学生信息,那么一个班级中有多个学生,这就是典型的一对多关系。
#创建班级表
create table t_class(
class_id int primary key auto_increment,
class_code varchar(20),
class_name varchar(20)
);
#创建学生表
create table t_student(
stu_id int primary key auto_increment,
class_id_fk int not null,
stu_name varchar(20),
stu_age int,
stu_address varchar(20)
);
#添加外键关系
ALTER TABLE t_student ADD CONSTRAINT class_id_fk FOREIGN KEY(class_id_fk) REFERENCES t_class(class_id);
#测试数据
insert into t_class values(null,'20190123','javaEE班');
insert into t_student values(null,1,'zhangsan',23,'西安');
insert into t_student values(null,1,'lisi',24,'北京');
insert into t_student values(null,1,'wangwu',25,'上海');
注意:外键通常都是由多方维护。
package com.click369.javabean;
import java.io.Serializable;
import java.util.List;
/**
* 保存班级信息的java实体类
* 当我们查询班级信息的时候需要连同这个班级中的所有学生信息一起得到,
* 所以我们需要在保存班级信息的java实体类中新增一个集合类型的成员变量,用来保存这个班级的所有学生信息
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class ClassBean implements Serializable{
private int classid;
private String classcode;
private String classname;
private List<StudentBean> studentList;
public int getClassid() {
return classid;
}
public void setClassid(int classid) {
this.classid = classid;
}
public String getClasscode() {
return classcode;
}
public void setClasscode(String classcode) {
this.classcode = classcode;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public List<StudentBean> getStudentList() {
return studentList;
}
public void setStudentList(List<StudentBean> studentList) {
this.studentList = studentList;
}
}
package com.click369.javabean;
import java.io.Serializable;
/**
* 保存学生信息的java实体类
* 当我们查询学生信息的时候需要连同这个学生所在班级的信息一起得到,
* 所以我们需要在保存学生信息的java实体类中新增一个成员变量,用来班级信息
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class StudentBean implements Serializable{
private int stuid;
private int classidfk;
private String stuname;
private int stuage;
private String stuaddress;
private ClassBean classBean;
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public int getClassidfk() {
return classidfk;
}
public void setClassidfk(int classidfk) {
this.classidfk = classidfk;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
public String getStuaddress() {
return stuaddress;
}
public void setStuaddress(String stuaddress) {
this.stuaddress = stuaddress;
}
public ClassBean getClassBean() {
return classBean;
}
public void setClassBean(ClassBean classBean) {
this.classBean = classBean;
}
}
package com.click369.mapper;
import com.click369.javabean.ClassBean;
/**
* 班级信息的数据访问接口
* @author Administrator
*
*/
public interface ClassBeanMapper {
//根据班级编号查询班级信息,并且得到这个班级的所有学生信息
ClassBean selectClassStudentByClassId(String classcode);
}
<?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.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>
ClassBeanMapper classMapper=session.getMapper(ClassBeanMapper.class);
ClassBean classBean=classMapper.selectClassStudentByClassId("20190123");
session.commit();
if(classBean!=null){
System.out.println(classBean.getClassname());
for(StudentBean stu:classBean.getStudentList()){
System.out.println(stu.getStuname()+"==="+stu.getStuaddress());
}
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==> Preparing: 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=?;
==> Parameters: 20190123(String)
<== Columns: class_id, class_code, class_name, stu_id, class_id_fk, stu_name, stu_age, stu_address
<== Row: 1, 20190123, javaEE班, 1, 1, zhangsan, 23, 西安
<== Row: 1, 20190123, javaEE班, 2, 1, lisi, 24, 北京
<== Row: 1, 20190123, javaEE班, 3, 1, wangwu, 25, 上海
<== Total: 3
javaEE班
zhangsan===西安
lisi===北京
wangwu===上海
//根据班级编号查询班级信息,并且得到这个班级的所有学生信息
ClassBean selectClassStudentByClassId2(String classcode);
<!-- 嵌套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>
ClassBeanMapper classMapper=session.getMapper(ClassBeanMapper.class);
ClassBean classBean=classMapper.selectClassStudentByClassId2("20190123");
session.commit();
if(classBean!=null){
System.out.println(classBean.getClassname());
for(StudentBean stu:classBean.getStudentList()){
System.out.println(stu.getStuname()+"==="+stu.getStuaddress());
}
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==> Preparing: 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=?;
==> Parameters: 20190123(String)
<== Columns: class_id, class_code, class_name, stu_id, class_id_fk, stu_name, stu_age, stu_address
<== Row: 1, 20190123, javaEE班, 1, 1, zhangsan, 23, 西安
<== Row: 1, 20190123, javaEE班, 2, 1, lisi, 24, 北京
<== Row: 1, 20190123, javaEE班, 3, 1, wangwu, 25, 上海
<== Total: 3
javaEE班
zhangsan===西安
lisi===北京
wangwu===上海
//根据班级编号查询班级信息,并且得到这个班级的所有学生信息
ClassBean selectClassStudentByClassId3(String classcode);
<!-- 嵌套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>
ClassBeanMapper classMapper=session.getMapper(ClassBeanMapper.class);
ClassBean classBean=classMapper.selectClassStudentByClassId3("20190123");
session.commit();
if(classBean!=null){
System.out.println(classBean.getClassname());
for(StudentBean stu:classBean.getStudentList()){
System.out.println(stu.getStuname()+"==="+stu.getStuaddress());
}
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==> Preparing: select * from t_class where class_code=?
==> Parameters: 20190123(String)
<== Columns: class_id, class_code, class_name
<== Row: 1, 20190123, javaEE班
====> Preparing: select * from t_student where class_id_fk=?
====> Parameters: 1(Integer)
<==== Columns: stu_id, class_id_fk, stu_name, stu_age, stu_address
<==== Row: 1, 1, zhangsan, 23, 西安
<==== Row: 2, 1, lisi, 24, 北京
<==== Row: 3, 1, wangwu, 25, 上海
<==== Total: 3
<== Total: 1
javaEE班
zhangsan===西安
lisi===北京
wangwu===上海
查询学生信息的时候需要连同这个学生所在班级的信息一起得到
package com.click369.mapper;
import com.click369.javabean.StudentBean;
/**
* 学生信息的数据访问接口
* @author Administrator
*
*/
public interface StudentBeanMapper {
//根据学生id查询学生信息的时候需要连同这个学生所在班级的信息一起得到
StudentBean selectStudentClassByStuid(int stuid);
}
<?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.StudentBeanMapper">
<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"/>
<association property="classBean" javaType="classBean" resultMap="classMap"></association>
</resultMap>
<resultMap type="classBean" id="classMap">
<id property="classid" column="class_id"/>
<result property="classcode" column="class_code"/>
<result property="classname" column="class_name"/>
</resultMap>
<select id="selectStudentClassByStuid" parameterType="int" resultMap="studentMap">
select s.stu_id,s.class_id_fk,s.stu_name,s.stu_age,s.stu_address,
c.class_id,c.class_code,c.class_name
from t_student as s right outer join t_class as c
on s.stu_id=#{stuid};
</select>
</mapper>
StudentBeanMapper studentMapper=session.getMapper(StudentBeanMapper.class);
StudentBean stuBean=studentMapper.selectStudentClassByStuid(3);
session.commit();
if(stuBean!=null){
System.out.println(stuBean.getStuname()+"==="+stuBean.getStuaddress()+"==="+stuBean.getClassBean().getClassname());
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
==> Preparing: select s.stu_id,s.class_id_fk,s.stu_name,s.stu_age,s.stu_address, c.class_id,c.class_code,c.class_name from t_student as s right outer join t_class as c on s.stu_id=?;
==> Parameters: 3(Integer)
<== Columns: stu_id, class_id_fk, stu_name, stu_age, stu_address, class_id, class_code, class_name
<== Row: 3, 1, wangwu, 25, 上海, 1, 20190123, javaEE班
<== Total: 1
wangwu===上海===javaEE班
3.mybatis的高级查询是多对多查询操作如何配置?
需求:根据角色id查询角色信息,并且得到角色所属组的内容
分析:通常情况下一个角色可以隶属于多个组,也可以是一个角色组中有多个角色,那么这个角色与这个角色所属组就是一中多对多关系,此时我们需要3张表,第一张表保存角色信息,第二张表保存角色所属组信息,第三张表是用来保存角色与角色所属组的关系的信息表。
注意的是多对多的关系是需要一张独立数据表来维护多对多的关系用的。
#创建角色表
create table t_role(
role_id int primary key auto_increment,
role_name varchar(20),
role_info varchar(20)
);
#创建角色所属组表
create table t_group(
group_id int primary key auto_increment,
group_name varchar(20),
group_info varchar(20)
);
#创建一个维护数据关系的中间表
create table t_role_group(
id int primary key auto_increment,
role_id_fk int,
group_id_fk int
);
#创建外键
ALTER TABLE t_role_group ADD CONSTRAINT role_id_fk FOREIGN KEY(role_id_fk) REFERENCES t_role(role_id);
ALTER TABLE t_role_group ADD CONSTRAINT group_id_fk FOREIGN KEY(group_id_fk) REFERENCES t_group(group_id);
#添加测试数据
insert into t_role values(null,'管理员','管理其他用户');
insert into t_role values(null,'普通用户','具有普通权限');
insert into t_group values(null,'CRM组','负责开发维护CRM项目');
insert into t_group values(null,'ERP组','负责开发维护ERP项目');
insert into t_role_group values(null,1,1);
insert into t_role_group values(null,1,2);
insert into t_role_group values(null,2,1);
insert into t_role_group values(null,2,2);
例如:
package com.click369.javabean;
import java.io.Serializable;
import java.util.List;
/**
* 保存角色信息的java实体类
* 由于我们在查询角色信息的时候需要得到角色所属的信息,
* 因此我们需要在保存角色信息的java类中创建一个集合类型成员变量,
* 用来保存角色所属组信息
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class RoleBean implements Serializable{
private int roleid;
private String rolename;
private String roleinfo;
private List<GroupBean> grouplist;
public int getRoleid() {
return roleid;
}
public void setRoleid(int roleid) {
this.roleid = roleid;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public String getRoleinfo() {
return roleinfo;
}
public void setRoleinfo(String roleinfo) {
this.roleinfo = roleinfo;
}
public List<GroupBean> getGrouplist() {
return grouplist;
}
public void setGrouplist(List<GroupBean> grouplist) {
this.grouplist = grouplist;
}
}
package com.click369.javabean;
import java.io.Serializable;
import java.util.List;
/**
* 保存角色所属组信息的java实体类
* 由于我们在查询角色所属组信息的时候需要得到角色的基本信息,
* 所以我们需要在保存角色所属组信息的java实体类中,创建一个集合类型的成员变量,
* 用来保存这个组中的角色信息
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class GroupBean implements Serializable{
private int groupid;
private String groupname;
private String groupinfo;
private List<RoleBean> rolelist;
public int getGroupid() {
return groupid;
}
public void setGroupid(int groupid) {
this.groupid = groupid;
}
public String getGroupname() {
return groupname;
}
public void setGroupname(String groupname) {
this.groupname = groupname;
}
public String getGroupinfo() {
return groupinfo;
}
public void setGroupinfo(String groupinfo) {
this.groupinfo = groupinfo;
}
public List<RoleBean> getRolelist() {
return rolelist;
}
public void setRolelist(List<RoleBean> rolelist) {
this.rolelist = rolelist;
}
}
package com.click369.mapper;
import com.click369.javabean.RoleBean;
/**
* 角色信息的数据访问接口
* @author Administrator
*
*/
public interface RoleBeanMapper {
//根据角色id查询角色信息,并得到角色所属组信息
RoleBean selectRoleAndGroupByRoleid(int roleid);
}
<?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.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>
try{
InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=factory.openSession();
RoleBeanMapper roleMapper=session.getMapper(RoleBeanMapper.class);
RoleBean role=roleMapper.selectRoleAndGroupByRoleid(2);
session.commit();
session.close();
List<GroupBean> grouplist=role.getGrouplist();
for(GroupBean group:grouplist){
System.out.println(role.getRolename()+" "+group.getGroupname());
}
}catch(Exception e){
e.printStackTrace();
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
==> Preparing: 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=?
==> Parameters: 2(Integer)
<== Columns: role_id, role_name, role_info, group_id, group_name, group_info
<== Row: 2, 普通用户, 具有普通权限, 1, CRM组, 负责开发维护CRM项目
<== Row: 2, 普通用户, 具有普通权限, 2, ERP组, 负责开发维护ERP项目
<== Total: 2
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3c0ecd4b]
Returned connection 1007603019 to pool.
普通用户 CRM组
普通用户 ERP组
package com.click369.mapper;
import com.click369.javabean.GroupBean;
/**
* 角色所属组信息的数据访问接口
* @author Administrator
*
*/
public interface GroupBeanMapper {
//根据组id查询组信息,并得到组中的角色信息
GroupBean selectGroupAndRoleByGroupId(int groupid);
}
<?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.GroupBeanMapper">
<resultMap type="groupBean" id="groupMap">
<id property="groupid" column="group_id"/>
<result property="groupname" column="group_name"/>
<result property="groupinfo" column="group_info"/>
<collection property="rolelist" ofType="roleBean">
<id property="roleid" column="role_id"/>
<result property="rolename" column="role_name"/>
<result property="roleinfo" column="role_info"/>
</collection>
</resultMap>
<select id="selectGroupAndRoleByGroupId" parameterType="int" resultMap="groupMap">
select g.group_id,g.group_name,g.group_info,
r.role_id,r.role_name,r.role_info
from t_group as g inner join t_role_group as rg
on g.group_id = rg.group_id_fk
inner join t_role as r
on r.role_id = rg.role_id_fk
where g.group_id=#{groupid}
</select>
</mapper>
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.GroupBean;
import com.click369.javabean.RoleBean;
import com.click369.mapper.GroupBeanMapper;
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();
GroupBeanMapper groupMapper=session.getMapper(GroupBeanMapper.class);
GroupBean group=groupMapper.selectGroupAndRoleByGroupId(2);
session.commit();
session.close();
List<RoleBean> rolelist=group.getRolelist();
for(RoleBean role:rolelist){
System.out.println(group.getGroupname()+" "+role.getRolename());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
==> Preparing: select g.group_id,g.group_name,g.group_info, r.role_id,r.role_name,r.role_info from t_group as g inner join t_role_group as rg on g.group_id = rg.group_id_fk inner join t_role as r on r.role_id = rg.role_id_fk where g.group_id=?
==> Parameters: 2(Integer)
<== Columns: group_id, group_name, group_info, role_id, role_name, role_info
<== Row: 2, ERP组, 负责开发维护ERP项目, 1, 管理员, 管理其他用户
<== Row: 2, ERP组, 负责开发维护ERP项目, 2, 普通用户, 具有普通权限
<== Total: 2
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
Returned connection 1333592072 to pool.
ERP组 管理员
ERP组 普通用户
4.MyBatis提供的分页查询原理?
分页方式:逻辑分页和物理分页。
逻辑分页:使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。
物理分页:自己手写 SQL 分页或使用分页插件 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);
List<PersonBean> personlist=new ArrayList<PersonBean>();
for(int i=1;i<=100;i++){
PersonBean person=new PersonBean();
person.setPersonname("zhangsan-"+i);
person.setPersonage(20+i);
person.setPersonaddress("address-"+i);
personlist.add(person);
}
personMapper.insertPerson(personlist);
session.commit();
session.close();
}catch(Exception e){
e.printStackTrace();
}
*/
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();
}
}
}
运行结果:
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@60c6f5b]
==> Preparing: SELECT count(0) FROM t_person
==> Parameters:
<== Columns: count(0)
<== Row: 100
<== Total: 1
==> Preparing: select * from t_person LIMIT ?, ?
==> Parameters: 90(Integer), 10(Integer)
<== Columns: person_id, person_name, person_age, person_address
<== Row: 91, zhangsan-91, 111, address-91
<== Row: 92, zhangsan-92, 112, address-92
<== Row: 93, zhangsan-93, 113, address-93
<== Row: 94, zhangsan-94, 114, address-94
<== Row: 95, zhangsan-95, 115, address-95
<== Row: 96, zhangsan-96, 116, address-96
<== Row: 97, zhangsan-97, 117, address-97
<== Row: 98, zhangsan-98, 118, address-98
<== Row: 99, zhangsan-99, 119, address-99
<== Row: 100, zhangsan-100, 120, address-100
<== Total: 10
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@60c6f5b]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@60c6f5b]
Returned connection 101478235 to pool.
当前页==10
每页数量==10
当前页的数量==10
总记录数==100
总页数==10
91 zhangsan-91
92 zhangsan-92
93 zhangsan-93
94 zhangsan-94
95 zhangsan-95
96 zhangsan-96
97 zhangsan-97
98 zhangsan-98
99 zhangsan-99
100 zhangsan-100