CREATE TABLE `emp` (
`id` int NOT NULL AUTO_INCREMENT,
`emp_name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`emp_gender` char(1) COLLATE utf8mb4_bin DEFAULT NULL,
`emp_email` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
public class Employee {
private Integer id;
private String empName;
private String empGender;
private String empEmail;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpGender() {
return empGender;
}
public void setEmpGender(String empGender) {
this.empGender = empGender;
}
public String getEmpEmail() {
return empEmail;
}
public void setEmpEmail(String empEmail) {
this.empEmail = empEmail;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", empName='" + empName + '\'' +
", empGender='" + empGender + '\'' +
", empEmail='" + empEmail + '\'' +
'}';
}
}
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.28version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="EmployeeMapper.xml"/>
mappers>
configuration>
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="per.xgt.mapper.EmployeeMapper">
<select id="selectEmp" resultType="per.xgt.entity.Employee">
select * from emp where id = #{id}
select>
mapper>
public class testMybatis {
/**
* 1.根据xml配置文件创建一个sqlSessionFactory对象
* 2.获取sqlSession实例,能直接执行已经映射的sql语句
* @throws IOException
*/
@Test
public void test1() throws IOException {
// 根据xml配置文件创建一个sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
Employee employee = sqlSession.selectOne("per.xgt.mapper.EmployeeMapper.selectEmp", 1);
System.out.println(employee);
sqlSession.close();
}
}
DEBUG 07-26 15:17:45,204 ==> Preparing: select * from emp where id = ? (BaseJdbcLogger.java:145)
DEBUG 07-26 15:17:45,230 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 07-26 15:17:45,293 <== Total: 1 (BaseJdbcLogger.java:145)
Employee{id=1, empName='null', empGender='null', empEmail='null'}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="per.xgt.mapper.EmployeeMapper">
<select id="selectEmp" resultType="per.xgt.entity.Employee">
select id,emp_name empName,emp_gender empGender,emp_email empEmail from emp where id = #{id}
select>
mapper>
public interface EmployeeMapper {
public Employee getEmpById(Integer id);
}
namespace="per.xgt.mapper.EmployeeMapper"
<select id="getEmpById" resultType="per.xgt.entity.Employee">
select id,emp_name empName,emp_gender empGender,emp_email empEmail from emp where id = #{id}
select>
mybatis会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
@Test
public void test2() throws IOException {
SqlSessionFactory sqlSessionFactory = get();
SqlSession sqlSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee emp = mapper.getEmpById(1);
System.out.println(emp);
sqlSession.close();
}
如果mapper文件在resource目录下,编译时可以直接找到,如果mapper文件在java目录下,则需要在pom文件中添加以下内容说明需要编译java文件下的mapper文件
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
<properties resource="jdbc.properties">properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
完整的settings配置
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
settings>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
运行结果
DEBUG 07-26 16:15:37,186 ==> Preparing: select * from emp where id = ? (BaseJdbcLogger.java:145)
DEBUG 07-26 16:15:37,213 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 07-26 16:15:37,275 <== Total: 1 (BaseJdbcLogger.java:145)
Employee{id=1, empName='tom', empGender='0', empEmail='tom@163.com'}
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写
<typeAliases>
<typeAlias type="per.xgt.entity.Employee" alias="emp"/>
typeAliases>
mapper文件使用别名
<select id="getEmpById" resultType="emp">
select * from emp where id = #{id}
select>
<typeAliases>
<typeAlias type="per.xgt.entity.Employee" alias="emp"/>
<package name="per.xgt.entity"/>
typeAliases>
@Alias("emp")
public class Employee
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<databaseIdProvider type="DB_VENDOR">
<property name="Mysql" value="mysql"/>
<property name="SQL Server" value="sqlserver"/>
<property name="DB2" value="db2"/>
<property name="Oracle" value="oracle" />
databaseIdProvider>
为sql指定数据库厂商
<select id="getEmpById" resultType="EMP" databaseId="mysql">
select * from emp where id = #{id}
select>
<mappers>
<mapper resource="EmployeeMapper.xml"/>
<mapper class="per.xgt.mapper.EmployeeMapperAnnotation"/>
mappers>
@Select("select * from emp where id = #{id}")
public Employee getEmpById(Integer id);
<mappers>
<mapper resource="EmployeeMapper.xml"/>
<mapper class="per.xgt.mapper.EmployeeMapperAnnotation"/>
<package name="per.xgt.mapper"/>
mappers>
package标签 name属性,映射该包下所有的sql映射文件 ,这种方式能够批量注册,并且每一对接口和xml名称必须相同
package per.xgt.mapper;
import per.xgt.entity.Employee;
/**
* @author gentao9527
* @version 1.0
* @date 2022/7/26 15:01
* @description
*/
public interface EmpMapper {
public Employee getEmpById(int id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="per.xgt.mapper.EmpMapper">
<select id="getEmpById" resultType="per.xgt.entity.Employee">
select * from emp where id = #{id}
select>
mapper>
public int insertEmp(Employee employee);
<insert id="insertEmp" parameterType="per.xgt.entity.Employee">
insert into emp values(null,#{empName},#{empGender},#{empEmail})
insert>
手动提交回滚测试代码
@Test
public void test2() throws IOException {
// 根据xml配置文件创建一个sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession实例,或渠道的SQLSession不会自动提交数据
SqlSession sqlSession = sqlSessionFactory.openSession();
Employee employee = new Employee();
employee.setEmpEmail("[email protected]");
employee.setEmpGender("1");
employee.setEmpName("xgt");
int insert = sqlSession.insert("per.xgt.mapper.EmployeeMapper.insertEmp", employee);
System.out.println(insert);
// 提交数据
sqlSession.commit();
// 回滚数据
sqlSession.rollback();
sqlSession.close();
}
sqlSessionFactory.openSession(true);里面参数true|false代表是否自动提交
如果有自增ID 新增执行SQL后不提交或者回滚,自增ID会有id不连续的问题
useGeneratedKeys:使用自增主键获取主键策略
keyProperty:指定对应的主键属性,也就是mybatis获取到主键值后,将封装给bean的哪个属性;
<insert id="insertEmpAndGetKey" parameterType="per.xgt.entity.Employee" useGeneratedKeys="true" keyProperty="id">
insert into emp values(null,#{empName},#{empGender},#{empEmail})
insert>
@Test
public void test3() throws IOException {
// 根据xml配置文件创建一个sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession实例,或渠道的SQLSession不会自动提交数据
SqlSession sqlSession = sqlSessionFactory.openSession(true);
Employee employee = new Employee();
employee.setEmpEmail("[email protected]");
employee.setEmpGender("1");
employee.setEmpName("wp");
int insert = sqlSession.insert("per.xgt.mapper.EmployeeMapper.insertEmpAndGetKey", employee);
System.out.println(employee);
sqlSession.close();
}
获取到的主键ID会自动封装到bean的主键属性
DEBUG 07-27 10:13:56,288 ==> Preparing: insert into emp values(null,?,?,?) (BaseJdbcLogger.java:145)
DEBUG 07-27 10:13:56,316 ==> Parameters: wp(String), 1(String), wp@163.com(String) (BaseJdbcLogger.java:145)
DEBUG 07-27 10:13:56,403 <== Updates: 1 (BaseJdbcLogger.java:145)
Employee{id=7, empName='wp', empGender='1', empEmail='wp@163.com'}
Oracle不支持自增自增,Oracle可以使用序列模拟自增;每次插入数据主键是从序列中拿到的值;
select SEQ.nextval from dual;
select SEQ.currval from dual;
<insert id="insertEmpAndGetKey" parameterType="per.xgt.entity.Employee" databaseId="oracle">
/*插入时的主键是从序列中拿到的
keyProperty:查询出的主键封装给bean的哪个属性
order:before当前sql在插入sql之前运行,after当前sql在插入之后运行
resultType:查处的数据的返回值类型
*/
<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
select EMPLOYEE_SEQ.NEXTVAL FROM DUAL
selectKey>
insert into emp values(#{id},#{empName},#{empGender},#{empEmail})
insert>
<insert id="insertEmpAndGetKey" parameterType="per.xgt.entity.Employee" databaseId="oracle">
/*插入时的主键是从序列中拿到的
keyProperty:查询出的主键封装给bean的哪个属性
order:before当前sql在插入sql之前运行,after当前sql在插入之后运行
resultType:查处的数据的返回值类型
*/
<selectKey keyProperty="id" order="AFTER" resultType="Integer">
select EMPLOYEE_SEQ.currval FROM DUAL
selectKey>
insert into emp values(EMPLOYEE_SEQ.NEXTVAL,#{empName},#{empGender},#{empEmail})
insert>
public Employee getEmp(int id,String name);
<select id="getEmp" resultType="per.xgt.entity.Employee">
select * from emp where id = #{param1} and empName = #{param2}
select>
可以使用全局配置,useActualParamName(jdk1.8),name=参数名
public Employee getEmp(@Param("id") int id,
@Param("name")String name);
<select id="getEmp" resultType="per.xgt.entity.Employee">
select * from emp where id = #{id} and empName = #{name}
select>
public int insertEmp(Employee employee);
<insert id="insertEmp" parameterType="per.xgt.entity.Employee">
insert into emp values(null,#{empName},#{empGender},#{empEmail})
insert>
public int insertEmpByMap(Map<String,Object> map);
<insert id="insertEmpByMap" parameterType="java.util.Map">
insert into emp values(null,#{empName},#{empGender},#{empEmail})
insert>
#{}:可以获取mao中的值,或者pojo对象属性的值;
${}:效果和#{}一样
DEBUG 07-27 11:21:33,179 ==> Preparing: select * from emp where id = 1 (BaseJdbcLogger.java:145)
DEBUG 07-27 11:21:33,210 ==> Parameters: (BaseJdbcLogger.java:145)
DEBUG 07-27 11:21:33,273 <== Total: 1 (BaseJdbcLogger.java:145)
Employee{id=1, empName='tom', empGender='0', empEmail='[email protected]'}
DEBUG 07-27 11:22:34,662 ==> Preparing: select * from emp where id = ? (BaseJdbcLogger.java:145)
DEBUG 07-27 11:22:34,687 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 07-27 11:22:34,775 <== Total: 1 (BaseJdbcLogger.java:145)
Employee{id=1, empName='tom', empGender='0', empEmail='[email protected]'}
<insert id="insertEmp" parameterType="per.xgt.entity.Employee">
insert into emp values(null,#{empName},#{empGender,jdbcType=NULL},#{empEmail})
insert>
还可以全局配置:jdbcTypeForNull=NULL;
》mode:存储过程
》numericScale:
》resultMap:
》typeHandler:
》jdbcTypeName:
public List<Employee> getAllEmployee();
<select id="getAllEmployee" resultType="per.xgt.entity.Employee">
select * from emp
select>
public Map<String,Object> getOneEmployeeByMap(int id);
<select id="getOneEmployeeByMap" resultType="java.util.Map">
select * from emp where id = #{id}
select>
@MapKey("empName")
public Map<String,Object> getOneEmployeeByMaps();
<select id="getOneEmployeeByMaps" resultType="per.xgt.entity.Employee">
select * from emp
select>
<resultMap id="myEmp" type="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="emp_name"/>
<result column="empGender" property="emp_gender"/>
<result column="empEmail" property="emp_email"/>
resultMap>
<select id="findOneById" resultMap="myEmp">
select * from emp where id = #{id}
select>
public class Employee {
private Integer id;
private String empName;
private String empGender;
private String empEmail;
private Department dept;
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", empName='" + empName + '\'' +
", empGender='" + empGender + '\'' +
", empEmail='" + empEmail + '\'' +
", dept=" + dept +
'}';
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpGender() {
return empGender;
}
public void setEmpGender(String empGender) {
this.empGender = empGender;
}
public String getEmpEmail() {
return empEmail;
}
public void setEmpEmail(String empEmail) {
this.empEmail = empEmail;
}
}
public class Department {
private Integer id;
private String deptName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", deptName='" + deptName + '\'' +
'}';
}
}
public Employee findOneAndDeptById(int id);
使用属性.属性赋值
<resultMap id="findOneAndDeptByIdMap" type="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="empName"/>
<result column="empGender" property="empGender"/>
<result column="empEmail" property="empEmail"/>
<result column="dId" property="dept.id"/>
<result column="deptName" property="dept.deptName"/>
resultMap>
<select id="findOneAndDeptById" resultMap="findOneAndDeptByIdMap">
SELECT e.id id,
e.emp_gender empGender,
e.emp_name empName,
e.emp_email empEmail,
d.id dId,
d.dept_name deptName
from emp e,dept d
where e.dept_id = d.id
and e.id = #{id};
select>
<resultMap id="findOneAndDeptByIdMapAssociation" type="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="empName"/>
<result column="empGender" property="empGender"/>
<result column="empEmail" property="empEmail"/>
<association property="dept" javaType="per.xgt.entity.Department">
<id column="dId" property="id"/>
<result column="deptName" property="deptName"/>
association>
resultMap>
<select id="findOneAndDeptById" resultMap="findOneAndDeptByIdMapAssociation">
SELECT e.id id,
e.emp_gender empGender,
e.emp_name empName,
e.emp_email empEmail,
d.id dId,
d.dept_name deptName
from emp e,dept d
where e.dept_id = d.id
and e.id = #{id};
select>
<resultMap id="findOneByStepAndIdMap" type="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="emp_name"/>
<result column="empGender" property="emp_gender"/>
<result column="empEmail" property="emp_email"/>
<association property="dept" select="per.xgt.mapper.DepartmentMapper.findOneById" column="dept_id">
association>
resultMap>
<select id="findOneByStepAndId" resultMap="findOneByStepAndIdMap">
select * from emp where id = #{id}
select>
public class Department {
private Integer id;
private String deptName;
private List<Employee> emps;
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", deptName='" + deptName + '\'' +
", emps=" + emps +
'}';
}
}
public Department findEmployeesByDept(Integer id);
<resultMap id="findEmployeesByDeptMap" type="per.xgt.entity.Department">
<id column="id" property="id"/>
<result column="deptName" property="deptName"/>
<collection property="emps" ofType="per.xgt.entity.Employee">
<id column="empId" property="id"/>
<result column="empName" property="empName"/>
<result column="empGender" property="empGender"/>
<result column="empEmail" property="empEmail"/>
collection>
resultMap>
<select id="findEmployeesByDept" resultMap="findEmployeesByDeptMap">
select d.id id,
d.dept_name deptName,
e.id empId,
e.emp_name empName,
e.emp_gender empGender,
e.emp_email empEmail
from dept d
left join emp e
on d.id = e.dept_id
where d.id = #{id}
select>
<resultMap id="findOneByStepAndIdMap" type="per.xgt.entity.Department">
<id column="id" property="id"/>
<result column="deptName" property="deptName"/>
<collection property="emps" select="per.xgt.mapper.EmployeeMapper.findAllByDeptId" column="id">
collection>
resultMap>
<select id="findOneByStepAndId" resultMap="findOneByStepAndIdMap">
select * from dept where id = #{id}
select>
将多列的值封装map传递
<resultMap id="findOneByStepAndIdMap" type="per.xgt.entity.Department">
<id column="id" property="id"/>
<result column="deptName" property="deptName"/>
<collection property="emps"
select="per.xgt.mapper.EmployeeMapper.findAllByDeptId"
column="{id=id}">
collection>
resultMap>
<select id="findOneByStepAndId" resultMap="findOneByStepAndIdMap">
select * from dept where id = #{id}
select>
column=“{key1=column1,key2=column2}”
<resultMap id="findOneByStepAndIdMap" type="per.xgt.entity.Department">
<id column="id" property="id"/>
<result column="deptName" property="deptName"/>
<collection property="emps"
select="per.xgt.mapper.EmployeeMapper.findAllByDeptId"
column="{id=id}" fetchType="lazy">
collection>
resultMap>
判断某列的值,改变封装行为;
<resultMap id="findOneByStepAndIdMapMore" type="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="emp_name"/>
<result column="empGender" property="emp_gender"/>
<result column="empEmail" property="emp_email"/>
<discriminator javaType="string" column="emp_gender">
<case value="0" resultType="per.xgt.entity.Employee">
<association property="dept" select="per.xgt.mapper.DepartmentMapper.findOneById" column="dept_id">
association>
case>
<case value="1" resultType="per.xgt.entity.Employee">
<id column="id" property="id"/>
<result column="empName" property="emp_name"/>
<result column="empGender" property="emp_gender"/>
<result column="empEmail" property="emp_name"/>
case>
discriminator>
resultMap>
<select id="findOneByStepAndId" resultMap="findOneByStepAndIdMapMore">
select * from emp where id = #{id}
select>
<select id="findEmpsByIf" parameterType="per.xgt.entity.Employee" resultType="per.xgt.entity.Employee">
select *
from emp
where 1 = 1
/*if test,判断表达式 OGNL
从参数中取值进行判断;
遇见特殊符号比如双引号,应该写转义字符;
*/
<if test="id != null">
and id = #{id}
if>
<if test="empName != null and empName != ''">
and emp_name = #{empName}
if>
/*OGNL会进行字符串与数字的转换判断*/
<if test="empGender == '0' or empGender == '1'">
and emp_gender = #{empGender}
if>
<if test="empEmail != null and empEmail.trim() != ''">
and emp_email = #{empEmail}
if>
select>
注意:
如果id == null,那么where后面直接就是 and emp_name = #{empName},所以需要在后面添上1=1;
解决上面if标签的问题,可以使用where标签来将所有的查询条件包括在内,会自动去掉第一个and或者or
<select id="findEmpsByIf" parameterType="per.xgt.entity.Employee" resultType="per.xgt.entity.Employee">
select *
from emp
<where>
<if test="id != null">
and id = #{id}
if>
<if test="empName != null and empName != ''">
and emp_name = #{empName}
if>
<if test="empGender == '0' or empGender == '1'">
and emp_gender = #{empGender}
if>
<if test="empEmail != null and empEmail.trim() != ''">
and emp_email = #{empEmail}
if>
where>
select>
**自定义字符串截取:**可以解决前面where标签的问题
<select id="findEmpsByTrim" resultType="per.xgt.entity.Employee">
select *
from emp
/*后面多出的and或者or where标签不能解决
prefix="":前缀,给整个拼接后的字符串添加一个前缀
prefixOverrides="":前缀覆盖,去掉整个前面多余的字符
suffix=“”:还给整个拼接后的字符串添加后缀
suffixOverrides="":后缀覆盖
*/
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id = #{id} and
if>
<if test="empName != null and empName != ''">
emp_name = #{empName} and
if>
<if test="empGender == '0' or empGender == '1'">
emp_gender = #{empGender} and
if>
<if test="empEmail != null and empEmail.trim() != ''">
emp_email = #{empEmail}
if>
trim>
select>
分支选择:
<select id="findEmpsByChoose" resultType="per.xgt.entity.Employee">
select * from emp
<where>
<choose>
<when test="id != null">
id = #{id}
when>
<when test="empName != null">
emp_name = #{empName}
when>
<when test="empGender != null">
emp_gender = #{empGender}
when>
<otherwise>
where 1 = 1
otherwise>
choose>
where>
select>
封装修改条件
问题:根据条件更新的时候,有可能会多出末尾的逗号","
<update id="updateEmpBySet" parameterType="per.xgt.entity.Employee">
update emp
set
<if test="empName != null">
emp_name = #{empName} ,
if>
<if test="empGender != null">
emp_gender = #{empGender} ,
if>
<if test="empEmail != null">
emp_email = #{empEmail}
if>
where id = #{id}
update>
解决:更新操作放在set标签
<update id="updateEmpBySet" parameterType="per.xgt.entity.Employee">
update emp
<set>
<if test="empName != null">
emp_name = #{empName} ,
if>
<if test="empGender != null">
emp_gender = #{empGender} ,
if>
<if test="empEmail != null">
emp_email = #{empEmail}
if>
set>
where id = #{id}
update>
也可以用trim解决问题:
<update id="updateEmpBySet" parameterType="per.xgt.entity.Employee">
update emp
<trim prefix="set" suffixOverrides=",">
<if test="empName != null">
emp_name = #{empName} ,
if>
<if test="empGender != null">
emp_gender = #{empGender} ,
if>
<if test="empEmail != null">
emp_email = #{empEmail}
if>
trim>
where id = #{id}
update>
但是如果所有条件都不满足,还是会报错;
遍历集合
public List<Employee> findEmpsByList(List<Integer> list);
<select id="findEmpsByList" resultType="per.xgt.entity.Employee">
select * from emp where id in
/*collection:指定要遍历的集合
list类型的参数会特殊处理封装在map中:map的key就是list
item:遍历出的元素赋值给指定的变量;
separator:每个元素之间的分隔符;
open:遍历的所有结果拼接出一个开始的字符;
open:遍历的所有结果拼接出一个结束的字符;
index:遍历list的时候是索引,遍历map的时候是map的key,item就是map的value
*/
<foreach collection="list" item="id" separator="," open="(" close=")" index="">
#{id}
foreach>
select>
public int addEmps(List<Employee> emps);
<insert id="addEmps" parameterType="java.util.List">
insert into emp (emp_name,emp_gender,emp_email,dept_id) values
<foreach collection="list" item="emp" separator=",">
(#{emp.empName},#{emp.empGender},#{emp.empEmail},#{emp.dept.id})
foreach>
insert>
注意点
1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可
也可以指定参数名
public int addEmps(@Param("emps") List<Employee> emps);
<insert id="addEmps" parameterType="java.util.List">
insert into emp (emp_name,emp_gender,emp_email,dept_id) values
<foreach collection="emps" item="emp" separator=",">
(#{emp.empName},#{emp.empGender},#{emp.empEmail},#{emp.dept.id})
foreach>
insert>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC&allowMultiQueries=true
jdbc.username=root
jdbc.password=root
<insert id="addEmps" parameterType="java.util.List">
<foreach collection="emps" item="emp" separator=";">
insert into emp (emp_name,emp_gender,emp_email,dept_id) values
(#{emp.empName},#{emp.empGender},#{emp.empEmail},#{emp.dept.id})
foreach>
insert>
<insert id="addEmpsOracle1" parameterType="java.util.List">
<foreach collection="emps" item="emp" open="begin" close="end;">
insert into emp (id,emp_name,emp_gender,emp_email,dept_id) values
(employee_seq,nextval,#{emp.empName},#{emp.empGender},#{emp.empEmail},#{emp.dept.id});
foreach>
insert>
<insert id="addEmpsOracle2" parameterType="java.util.List">
insert into emp (id,emp_name,emp_gender,emp_email,dept_id)
select employees_seq.nextval,emp_name,emp_gender,emp_email,dept_id
from
<foreach collection="emps" item="emp" separator="union" open="(" close=")">
select #{emp.empName} emp_name,
#{emp.empGender} emp_gender,
#{empempEmail} emp_email,
#{emp.dept.id} dept_id
from dual
foreach>
insert>
不只是方法参数传递的参数可以判断,mybatis默认还有两个内置参数;
可以将OGNL表达式的值绑定到一个变量中,方便后面引用
<select id="getEmpByLikeBind" resultType="per.xgt.entity.Employee">
<bind name="_name" value="'%' + empName + '%'"/>
select *
from emp
where id = #{value}
and emp_name like #{_name}
select>
sql:抽取可重用的sql片段
include:引用一斤股抽取的sql
<sql id="insertColumn">
<if test="_databaseId == 'mysql'">
(id,emp_name,emp_gender,emp_email,${aa})
if>
<if test="_databaseId == 'oracle'">
(emp_name,emp_gender,emp_email)
if>
sql>
<insert id="addOne">
insert into emp
/*引用抽出的sql片段*/
<include refid="insertColumn">
<property name="aa" value="vvv"/>
include>
<if test="_databaseId == 'mysql'">
values (null,'tom','0','[email protected]')
if>
<if test="_databaseId == 'oracle'">
values ('tom','0','[email protected]')
if>
insert>
mybatis系统中默认定义了两级缓存
本地缓存:与数据库同一次会话期间查询到的数据会被放在本地缓存中,以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据;
sqlSession.clearCache();
全局缓存:基于namespace级别的缓存,一个namespace对应一个二级缓存;
》一个会话查询一条数据,这条数据就会被放在当前会话的一级缓存中;
》如果会话关闭,一级缓存的数据会被保存到二级缓存中,新的会话查询信息,就可以参照二级缓存的内容;
》如果SqlSesison使用了多个namespace,不同namespace查询出的数据会放到自己对应的缓存中;
public class Employee implements Serializable
<setting name="cacheEnabled" value="true"/>
<cache eviction="LRU" flushInterval="1000*60*5" readOnly="false" size="1024" blocking="">cache>
查询的数据会从二级缓存中获取,但是查出的数据会被默认先放在一级缓存中,只有会话提交或者关闭后,一级缓存的数据才会转移到二级缓存
<select id="getEmpById" resultType="per.xgt.entity.Employee" useCache="true">
select *
from emp
where id = #{value}
select>
查询和更新操作的标签:flushCache=“true”,执行完后会清除一级和二级缓存;
全局配置:mybatis3.3后->localCacheScope:本地缓存作用域,SESSION|STATEMENT,STATEMENT代表不共享当前数据,可以禁用掉一级缓存;
二级缓存》一级缓存》数据库
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.0.3version>
dependency>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
ehcache>
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
cache>
<cache-ref namespace="per.xgt.mapper.DepartmentMapper"/>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>per.xgtgroupId>
<artifactId>mybatis-04-ssmartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>mybatis-04-ssm Maven Webappname>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>net.sourceforge.cglibgroupId>
<artifactId>com.springsource.net.sf.cglibartifactId>
<version>2.2.0version>
dependency>
<dependency>
<groupId>org.aopalliancegroupId>
<artifactId>com.springsource.org.aopallianceartifactId>
<version>1.0.0version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>com.springsource.org.aspectj.weaverartifactId>
<version>1.7.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.1.3version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-expressionartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.29version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-ormartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>4.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.apache.taglibsgroupId>
<artifactId>taglibs-standard-implartifactId>
<version>1.2.1version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.apache.taglibsgroupId>
<artifactId>taglibs-standard-specartifactId>
<version>1.2.1version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.3.0version>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
project>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC&allowMultiQueries=true
jdbc.username=root
jdbc.password=root
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>SSMdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<filter>
<filter-name>characterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>trueparam-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="per.xgt" use-default-filters="true">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/">property>
<property name="suffix" value=".jsp">property>
bean>
<mvc:default-servlet-handler/>
<mvc:annotation-driven>mvc:annotation-driven>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<context:component-scan base-package="per.xgt">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}">property>
<property name="jdbcUrl" value="${jdbc.url}">property>
<property name="user" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="configLocation" value="classpath:mybatis-config.xml">property>
<property name="mapperLocations" value="classpath*:per/xgt/dao/*.xml">property>
bean>
<mybatis-spring:scan base-package="per.xgt.dao" />
<tx:annotation-driven />
beans>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
configuration>
public class Employee {
private Integer id;
private String empName;
private String empGender;
private String empEmail;
public Employee(Integer id, String empName, String empGender, String empEmail) {
this.id = id;
this.empName = empName;
this.empGender = empGender;
this.empEmail = empEmail;
}
public Employee() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpGender() {
return empGender;
}
public void setEmpGender(String empGender) {
this.empGender = empGender;
}
public String getEmpEmail() {
return empEmail;
}
public void setEmpEmail(String empEmail) {
this.empEmail = empEmail;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", empName='" + empName + '\'' +
", empGender='" + empGender + '\'' +
", empEmail='" + empEmail + '\'' +
'}';
}
}
public interface EmployeeMapper {
public Employee findOneById(Integer id);
public List<Employee> findAllEmps();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="per.xgt.dao.EmployeeMapper">
<select id="findOneById" resultType="per.xgt.entity.Employee">
select * from emp where id = #{id}
select>
<select id="findAllEmps" resultType="per.xgt.entity.Employee">
select * from emp
select>
mapper>
public interface EmployeeService {
public List<Employee> findAllEmps();
}
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
public List<Employee> findAllEmps() {
List<Employee> emps = employeeMapper.findAllEmps();
return emps;
}
}
@Controller
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@RequestMapping("findAllEmps")
public String emps(Map<String,Object> map){
List<Employee> emps = employeeService.findAllEmps();
for (Employee emp : emps) {
System.out.println(emp);
}
map.put("emps", emps);
return "list";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<h2>Hello World!h2>
<a href="findAllEmps">查询所有员工a>
body>
html>
<%--
Created by IntelliJ IDEA.
User: Valen
Date: 2022/7/28
Time: 16:53
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<table>
<tr>
<td>idtd>
<td>empNametd>
<td>empGendertd>
<td>empEmailtd>
tr>
<c:forEach items="${emps}" var="emp">
<tr>
<td>${emp.id}td>
<td>${emp.empName}td>
<td>${emp.empGender}td>
<td>${emp.empEmail}td>
tr>
c:forEach>
table>
body>
html>
所有mybatis对象,都会通过下面封装后返回
parameterHandler =
(ParameterHandler)this.interceptorChain.pluginAll(parameterHandler);
方法内部:获取所有的Interceprot(插件实现接口)(拦截器)
public Object pluginAll(Object target) {
Interceptor interceptor;
for(Iterator i$ = this.interceptors.iterator(); i$.hasNext(); target = interceptor.plugin(target)) {
interceptor = (Interceptor)i$.next();
}
return target;
}
// 返回target对象
target = interceptor.plugin(target))
插件机制:创建代理对象,通过增强拦截每一个方法执行,然后在方法前后执行增强方法
public class MyPluginA implements Interceptor {
/**
* 拦截目标对象的目标方法的执行;
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 执行目标方法
Object proceed = invocation.proceed();
// 返回执行后的返回值
return proceed;
}
/**
* 包装梅花表对象,为目标对象创建一个代理对象
* @param o
* @return
*/
@Override
public Object plugin(Object o) {
// 接住Plugin类的wrap方法来使用当前Interceptor包装目标对象
Object wrap = Plugin.wrap(o, this);
// 返回动态代理对象
return wrap;
}
/**
* 将插件注册时的property属性设置进来
* @param properties
*/
@Override
public void setProperties(Properties properties) {
System.out.println("插件配置的信息:" + properties);
}
}
// 完成插件签名,告诉mybatis当前插件用来拦截哪个对象的哪个方法;
@Intercepts({
@Signature(type = StatementHandler.class,method = "parameterize",args = java.sql.Statement.class)
})
<plugins>
<plugin interceptor="per.xgt.config.MyPluginA">
<property name="username" value="root"/>
<property name="password" value="root"/>
plugin>
plugins>
创建动态代理的时候,是按照插件配置顺序创建层层代理对象,执行目标方法的之后,按照逆向顺序执行;
// 完成插件签名,告诉mybatis当前插件用来拦截哪个对象的哪个方法;
@Intercepts({
@Signature(type = StatementHandler.class,method = "parameterize",args = java.sql.Statement.class)
})
public class MyPluginA implements Interceptor {
/**
* 拦截目标对象的目标方法的执行;
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("intercept===:"+invocation.getMethod());
// 改变方法参数
System.out.println("当前拦截的目标对象:"+invocation.getTarget());
Object target = invocation.getTarget();
// 拿到target的源数据
MetaObject metaObject = SystemMetaObject.forObject(target);
Object value = metaObject.getValue("parameterHandler.parameterObject");
System.out.println("所有参数:"+value);
// 修改完要用的参数
metaObject.setValue("parameterHandler.parameterObject",10);
// 执行目标方法
Object proceed = invocation.proceed();
// 返回执行后的返回值
return proceed;
}
/**
* 包装梅花表对象,为目标对象创建一个代理对象
* @param o
* @return
*/
@Override
public Object plugin(Object o) {
System.out.println("plugin===:" + o);
// 接住Plugin类的wrap方法来使用当前Interceptor包装目标对象
Object wrap = Plugin.wrap(o, this);
// 返回动态代理对象
return wrap;
}
/**
* 将插件注册时的property属性设置进来
* @param properties
*/
@Override
public void setProperties(Properties properties) {
System.out.println("插件配置的信息===:" + properties);
}
}
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.0.0version>
dependency>
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
configuration>
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="configLocation" value="classpath:mybatis-config.xml">property>
<property name="mapperLocations" value="classpath*:per/xgt/dao/*.xml">property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysqlprop>
props>
property>
bean>
array>
property>
bean>
分页插件可选参数如下:
下面几个参数都是针对默认 dialect 情况下的参数。使用自定义 dialect 实现时,下面的参数没有任何作用。
重要提示:当 offsetAsPageNum=false 的时候,由于 PageNum 问题,RowBounds查询的时候 reasonable 会强制为 false。使用 PageHelper.startPage 方法不受影响。
@RequestMapping("findAllEmps")
public String emps(Map<String,Object> map){
PageHelper.startPage(1, 5);
List<Employee> emps = employeeService.findAllEmps();
System.out.println("======");
for (Employee emp : emps) {
System.out.println(emp);
}
System.out.println("======");
PageInfo<Employee> list = new PageInfo<Employee>(emps);
map.put("pageInfo", list);
System.out.println(list);
List<Employee> employees = list.getList();
for (Employee employee : employees) {
System.out.println(employee);
}
return "list";
}
注意:
public class PageInfo<T> implements Serializable {
private static final long serialVersionUID = 1L;
//当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的数量
private int size;
//由于startRow 和endRow 不常用,这里说个具体的用法
//可以在页面中"显示startRow 到endRow 共size 条数据"
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总记录数
private long total;
//总页数
private int pages;
//结果集
private List<T> list;
//前一页
private int prePage;
//下一页
private int nextPage;
//是否为第一页
private boolean isFirstPage = false;
//是否为最后一页
private boolean isLastPage = false;
//是否有前一页
private boolean hasPreviousPage = false;
//是否有下一页
private boolean hasNextPage = false;
//导航页码数
private int navigatePages;
//所有导航页号
private int[] navigatepageNums;
//导航条上的第一页
private int navigateFirstPage;
//导航条上的最后一页
private int navigateLastPage;
}
public class Page<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
//当前页码
private int pageNum;
//每一页记录数
private int pageSize;
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总记录数
private long total;
//总页码
private int pages;
//
private boolean count;
//
private Boolean reasonable;
//
private Boolean pageSizeZero;
}
@Test
public void test18() throws IOException {
SqlSessionFactory sqlSessionFactory = get();
// 可以执行批量操作的SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
long start = System.currentTimeMillis();
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
for (int i = 0; i < 10000; i++) {
employee.setEmpGender(i%2==0?"0":"1");
employee.setEmpName("批量"+(i+1));
employee.setEmpEmail(employee.getEmpName() + "@163.com");
int batch = mapper.addEmpsBatch(employee);
}
sqlSession.commit();
long end = System.currentTimeMillis();
sqlSession.close();
System.out.println("执行时长:" + (end - start));
}
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean">constructor-arg>
<constructor-arg name="executorType" value="BATCH">constructor-arg>
bean>
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Autowired
private SqlSession sqlSession;
@Override
public List<Employee> findAllEmps() {
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
// 执行批量操作
/*
* xxxxxx
* */
List<Employee> emps = employeeMapper.findAllEmps();
return emps;
}
}
使用游标返回数据列表
public class Page {
private int start;
private int end;
private int count;
private List<Employee> emps;
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<Employee> getEmps() {
return emps;
}
public void setEmps(List<Employee> emps) {
this.emps = emps;
}
}
<select id="getPageByProcedure" statementType="CALLABLE" databaseId="oracle">
{
call emp_getpage(
#{start,mode=IN,jdbcType=INTEGER},
#{end,mode=IN,jdbcType=INTEGER},
#{count,mode=OUT,jdbcType=INTEGER},
#{emps,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=pageEmp}
)
}
select>
<resultMap id="pageEmp" type="per.xgt.entity.Employee">
<id column="id" property="id" />
<result column="emp_name" property="empName" />
<result column="emp_email" property="empEmail" />
<result column="emp_gender" property="empGender" />
resultMap>
mybatis 处理枚举类型默认是存储枚举的名字,可以改为存储枚举的索引
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="per.xgt.entity.EmpStatus"/>
typeHandlers>
public enum EmpStatus {
LOGIN,LOGOUT,REMOVE
}
public class Employee implements Serializable {
private Integer id;
private String empName;
private String empGender;
private String empEmail;
private Department dept;
// 员工状态
private EmpStatus empStatus = EmpStatus.LOGOUT;
public EmpStatus getEmpStatus() {
return empStatus;
}
public void setEmpStatus(EmpStatus empStatus) {
this.empStatus = empStatus;
}
public Employee(Integer id, String empName, String empGender, String empEmail, EmpStatus empStatus) {
this.id = id;
this.empName = empName;
this.empGender = empGender;
this.empEmail = empEmail;
this.empStatus = empStatus;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", empName='" + empName + '\'' +
", empGender='" + empGender + '\'' +
", empEmail='" + empEmail + '\'' +
", dept=" + dept +
", empStatus=" + empStatus +
'}';
}
public Employee() {
}
public Employee(Integer id, String empName, String empGender, String empEmail, Department dept) {
this.id = id;
this.empName = empName;
this.empGender = empGender;
this.empEmail = empEmail;
this.dept = dept;
}
public Employee(Integer id, String empName, String empGender, String empEmail) {
this.id = id;
this.empName = empName;
this.empGender = empGender;
this.empEmail = empEmail;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpGender() {
return empGender;
}
public void setEmpGender(String empGender) {
this.empGender = empGender;
}
public String getEmpEmail() {
return empEmail;
}
public void setEmpEmail(String empEmail) {
this.empEmail = empEmail;
}
}
public int insertEmpByEnum(Employee employee);
<insert id="insertEmpByEnum" parameterType="per.xgt.entity.Employee" useGeneratedKeys="true" keyProperty="id">
insert into emp (emp_name,emp_gender,emp_email,emp_status)
values (#{empName},#{empGender},#{empEmail},#{empStatus})
insert>
测试
@Test
public void test19() throws IOException {
SqlSessionFactory sqlSessionFactory = get();
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee(null, "enum", "1", "[email protected]");
mapper.insertEmpByEnum(employee);
System.out.println(employee.getId());
sqlSession.close();
}
public enum EmpStatus {
LOGIN(1001,"已登录"),
LOGOUT(1002,"已登出"),
REMOVE(1003,"不存在");
private Integer code;
private String msg;
private EmpStatus(int code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public static EmpStatus getEmpStatusByCode(Integer code){
switch (code){
case 1001:return LOGIN;
case 1002:return LOGOUT;
case 1003:return REMOVE;
default:return LOGOUT;
}
}
}
<typeHandlers>
<typeHandler handler="per.xgt.config.MyEnumHandler" javaType="per.xgt.entity.EmpStatus"/>
typeHandlers>
#{empStatus,typeHandler=per.xgt.config.MyEnumHandler}
如果是查询可以在resultMap中指定
<result column="empName" property="emp_name" typeHandler="per.xgt.config.MyEnumHandler"/>