通用Mapper

难度4,知识点比较琐碎,不过比hibernate简单。学完MyBatis Spring再来学这里。

第一部分:理论

1,创建测试数据

CREATE TABLE `tabple_emp` ( 
`emp_id` int NOT NULL AUTO_INCREMENT , 
`emp_name` 
varchar(500) NULL , 
`emp_salary` 
double(15,5) NULL , 
`emp_age` int NULL , 
PRIMARY KEY (`emp_id`) 
);
INSERT INTO `tabple_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('tom', '1254.37', '27'); 
INSERT INTO `tabple_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('jerry', '6635.42', '38'); 
INSERT INTO `tabple_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('bob', '5560.11', '40'); 
INSERT INTO `tabple_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('kate', '2209.11', '22'); 
INSERT INTO `tabple_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('justin', '4203.15', '30');

实体类

public class Employee { 
private Integer empId; 
private String empName; 
private Double empSalary; 
private Integer empAge; 
public Employee() { 
}
public Employee(Integer empId, String empName, Double empSalary, Integer empAge) { 
super(); 
this.empId = empId; 
this.empName = empName; 
this.empSalary = empSalary; 
this.empAge = empAge; 
}
@Override 
public String toString() { 
return "Employee [empId=" + empId + ", empName=" + empName + ", empSalary=" + empSalary + ", empAge=" + empAge 
+ "]"; 
}
public Integer getEmpId() { 
return empId; 
}
public void setEmpId(Integer empId) { 
this.empId = empId; 
}
public String getEmpName() { 
return empName; 
}
public void setEmpName(String empName) { 
this.empName = empName; 
}
public Double getEmpSalary() {
return empSalary; 
}
public void setEmpSalary(Double empSalary) { 
this.empSalary = empSalary; 
}
public Integer getEmpAge() { 
return empAge; 
}
public void setEmpAge(Integer empAge) { 
this.empAge = empAge; 
} 
}

Java 实体类

考虑到基本数据类型在 Java 类中都有默认值,会导致 MyBatis 在执行相关操作

时很难判断当前字段是否为 null,所以在 MyBatis 环境下使用 Java 实体类时尽量不

要使用基本数据类型,都使用对应的包装类型。

2,搭建 MyBatis+Spring 开发环境

集成 Mapper

加入 Maven 依赖信息

<dependency>

<groupId>tk.mybatis</groupId>

<artifactId>mapper</artifactId>

<version>4.0.0-beta3</version>

</dependency>

Ø

修改 Spring 配置文件

<!-- 整合通用 Mapper 所需要做的配置修改: -->

<!-- 原始全类名:org.mybatis.spring.mapper.MapperScannerConfigurer -->

<!-- 通用 Mapper 使用:tk.mybatis.spring.mapper.MapperScannerConfigurer -->

<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">

<property name="basePackage" value="com.atguigu.mapper.mappers"/>

</bean>

第一个操作

/**

* 具 体 操 作 数 据 库 的 Mapper 接 口 , 需 要 继 承 通 用 Mapper 提 供 的 核 心 接 口 :

Mapper<Employee>

* 泛型类型就是实体类的类型

* @author Lenovo

*

*/

public interface EmployeeMapper extends Mapper<Employee> {

}

3,常用注解

3.1@Table 注解

作用:建立实体类和数据库表之间的对应关系。

默认规则:实体类类名首字母小写作为表名。Employee 类→employee 表。

用法:在@Table 注解的 name 属性中指定目标数据库表的表名

 

3.2@Column 注解

作用:建立实体类字段和数据库表字段之间的对应关系。

默认规则:

实体类字段:驼峰式命名

数据库表字段:使用“_”区分各个单词

用法:在@Column 注解的 name 属性中指定目标字段的字段名

 

3.3@Id 注解

通用 Mapper 在执行 xxxByPrimaryKey(key)方法时,有两种情况。

情况 1:没有使用@Id 注解明确指定主键字段

SELECT emp_id,emp_name,emp_salary_apple,emp_age FROM tabple_emp WHERE emp_id = ?

AND emp_name = ? AND emp_salary_apple = ? AND emp_age = ?

之所以会生成上面这样的 WHERE 子句是因为通用 Mapper 将实体类中的所有

字段都拿来放在一起作为联合主键。

情况 2:使用@Id 主键明确标记和数据库表中主键字段对应的实体类字段。

 

3.4@GeneratedValue 注解

作用:让通用 Mapper 在执行 insert 操作之后将数据库自动生成的主键值回写到实

体类对象中。

自增主键用法:

 序列主键用法:

 

应用场景:购物车结账

Ø 增加商品销量...

Ø 减少商品库存...

Ø 生成订单数据→封装到 Order 对象中→保存 Order 对象→数据库自动生成主键

值→回写到实体类对象 Order

Ø 生成一系列订单详情数据→List<OrderItem>→在每一个 OrderItem 中设置

Order 对象的主键值作为外键→批量保存 List<OrderItem>

……

3.5@Transient 主键

用于标记不与数据库表字段对应的实体类字段。

@Transient

private String otherThings; //非数据库表中字段

4 常用方法

4.1selectOne 方法

Ø 通用 Mapper 替我们自动生成的 SQL 语句情况

 

实体类封装查询条件生成 WHERE 子句的规则

n 使用非空的值生成 WHERE 子句

n 在条件表达式中使用“=”进行比较

Ø 要求必须返回一个实体类结果,如果有多个,则会抛出异常

4.2xxxByPrimaryKey 方法

需要使用@Id 主键明确标记和数据库表主键字段对应的实体类字段,否则通用

Mapper 会将所有实体类字段作为联合主键。

4.3xxxSelective 方法

非主键字段如果为 null 值,则不加入到 SQL 语句中。

5 QBC 查询

5.1概念

Query By Criteria

Criteria Criterion 的复数形式。意思是:规则、标准、准则。在 SQL 语句中相当

于查询条件。

QBC 查询是将查询条件通过 Java 对象进行模块化封装。

5.2示例代码


//目标:WHERE (emp_salary>? AND emp_age<?) OR (emp_salary<? AND emp_age>?) 
//1.创建 Example 对象 
Example example = new Example(Employee.class); 
//*********************** 
//i.设置排序信息 
example.orderBy("empSalary").asc().orderBy("empAge").desc(); 
//ii.设置“去重” 
example.setDistinct(true); 
//iii.设置 select 字段 
example.selectProperties("empName","empSalary"); 
//*********************** 
//2.通过 Example 对象创建 Criteria 对象
Criteria criteria01 = example.createCriteria(); 
Criteria criteria02 = example.createCriteria(); 
//3.在两个 Criteria 对象中分别设置查询条件 
//property 参数:实体类的属性名 
//value 参数:实体类的属性值 
criteria01.andGreaterThan("empSalary", 3000) 
.andLessThan("empAge", 25); 
criteria02.andLessThan("empSalary", 5000) 
.andGreaterThan("empAge", 30); 
//4.使用 OR 关键词组装两个 Criteria 对象 
example.or(criteria02); 
//5.执行查询 
List<Employee> empList = employeeService.getEmpListByExample(example); 
for (Employee employee : empList) { 
System.out.println(employee); 
}

下面的就直接截图了

 

 

 

7.3配置 MapperScannerConfigurer 注册 MyMapper<T>

<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">

<property name="basePackage" value="com.atguigu.mapper.mappers"/>

<property name="properties">

<value>

mappers=com.atguigu.mapper.mine_mappers.MyMapper

</value>

</property>

</bean>

8 通用 Mapper 接口扩展

8.1说明

这里的扩展是指增加通用 Mapper 没有提供的功能。

8.2举例

通用 Mapper 官方文档中使用一个批量 insert 作为扩展功能的例子:

tk.mybatis.mapper.additional.insert.InsertListMapper<T>

tk.mybatis.mapper.additional.insert.InsertListProvider

我们来仿照写一个批量 update。假设我们想生成下面这样的 SQL 语句:

UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ;

UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ;

UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ;

……

为了生成上面那样的 SQL 语句,我们需要使用到 MyBatis foreach 标签。

<foreach collection="list" item="record" separator=";" >

UPDATE tabple_emp

SET emp_name=#{record.empName},

emp_age=#{record.empAge},

emp_salary=#{record.empSalary}

where emp_id=#{record.empId}

</foreach>

 

 

 

 

 

 

第二部分:案例

常用方法:

目录

 Employee.java


package com.atguigu.mapper.entities;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="tabple_emp")
public class Employee {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer empId;//emp_id
	
	private String empName;//emp_name
	
	@Column(name="emp_salary_apple")
	private Double empSalary;//emp_salary_apple
	
	private Integer empAge;//emp_age
	
	public Employee() {
		
	}

	public Employee(Integer empId, String empName, Double empSalary, Integer empAge) {
		super();
		this.empId = empId;
		this.empName = empName;
		this.empSalary = empSalary;
		this.empAge = empAge;
	}

	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", empName=" + empName + ", empSalary=" + empSalary + ", empAge=" + empAge
				+ "]";
	}

	public Integer getEmpId() {
		return empId;
	}

	public void setEmpId(Integer empId) {
		this.empId = empId;
	}

	public String getEmpName() {
		return empName;
	}

	public void setEmpName(String empName) {
		this.empName = empName;
	}

	public Double getEmpSalary() {
		return empSalary;
	}

	public void setEmpSalary(Double empSalary) {
		this.empSalary = empSalary;
	}

	public Integer getEmpAge() {
		return empAge;
	}

	public void setEmpAge(Integer empAge) {
		this.empAge = empAge;
	}

}

EmployeeMapper.java

package com.atguigu.mapper.mappers;

import com.atguigu.mapper.entities.Employee;

import tk.mybatis.mapper.common.Mapper;

/**
 * 具体操作数据库的Mapper接口,需要继承通用Mapper提供的核心接口:Mapper<Employee>
 * 泛型类型就是实体类的类型
 * @author Lenovo
 *
 */
public interface EmployeeMapper extends Mapper<Employee> {
	
}

EmployeeService.java

package com.atguigu.mapper.services;

import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.atguigu.mapper.entities.Employee;
import com.atguigu.mapper.mappers.EmployeeMapper;

import tk.mybatis.mapper.entity.Example;

//通用mapper方法  这个里面的方法视频里面老师都走过一遍,要求掌握,很重要!!!!
@Service
public class EmployeeService {
	
	@Autowired
	private EmployeeMapper employeeMapper;

	public Employee getOne(Employee employeeQueryCondition) {
		
		return employeeMapper.selectOne(employeeQueryCondition);
	}

	public Employee getEmployeeById(Integer empId) {
		return employeeMapper.selectByPrimaryKey(empId);
	}

	public boolean isExists(Integer empId) {
		return employeeMapper.existsWithPrimaryKey(empId);
	}

	public void saveEmployee(Employee employee) {
		employeeMapper.insert(employee);
	}

	public void saveEmployeeSelective(Employee employee) {
		employeeMapper.insertSelective(employee);
	}

	public void updateEmployeeSelective(Employee employee) {
		employeeMapper.updateByPrimaryKeySelective(employee);
	}

	public void removeEmployee(Employee employee) {
		employeeMapper.delete(employee);
	}

	public void removeEmployeeById(Integer empId) {
		employeeMapper.deleteByPrimaryKey(empId);
	}

	public List<Employee> getEmpListByExample(Example example) {
		return employeeMapper.selectByExample(example);
	}

	public List<Employee> getEmpListByRowBounds(RowBounds rowBounds) {
		return employeeMapper.selectByRowBounds(null, rowBounds);
	}

}

jdbc.properties

jdbc.user=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/common_mapper?useUnicode=true&characterEncoding=utf8
jdbc.driver=com.mysql.jdbc.Driver

log4j.properties

log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.ImmediateFlush=true
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

log4j.logger.com.mchange.v2=ERROR

mybatis-config.xml


<?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>

</configuration>

spring-context.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
	
	<!-- 配置数据源 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>

	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="driverClass" value="${jdbc.driver}"/>
	</bean>

	<!-- 整合MyBatis -->
	<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- 整合通用Mapper所需要做的配置修改: -->
	<!-- 原始全类名:org.mybatis.spring.mapper.MapperScannerConfigurer -->
	<!-- 通用Mapper使用:tk.mybatis.spring.mapper.MapperScannerConfigurer -->
	<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.atguigu.mapper.mappers"/>
	</bean>

	<!-- 配置Service自动扫描的包 -->
	<context:component-scan base-package="com.atguigu.mapper.services"/>

	<!-- 配置声明式事务 -->
	<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*Service.*(..))"/>
	</aop:config>

	<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="save*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
			<tx:method name="remove*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
			<tx:method name="update*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
		</tx:attributes>
	</tx:advice>
</beans>

EmployeeMapperTest.java


package com.atguigu.mapper.test;

import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.atguigu.mapper.entities.Employee;
import com.atguigu.mapper.services.EmployeeService;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

public class EmployeeMapperTest {
	
	private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-context.xml");
	private EmployeeService employeeService = iocContainer.getBean(EmployeeService.class);
	//==================常用方法========================================
	@Test
	public void testSelectOne() {
		
		//1.创建封装查询条件的实体类对象
		Employee employeeQueryCondition = new Employee(null, "bob", 5560.11, null);
		
		//2.执行查询
		Employee employeeQueryResult = employeeService.getOne(employeeQueryCondition);
		
		//3.打印
		System.out.println(employeeQueryResult);
	}

	@Test
	public void testSelect() {
		
	}

	@Test
	public void testSelectAll() {
		
	}

	@Test
	public void testSelectCount() {
		
	}

	@Test
	public void testSelectByPrimaryKey() {
		
		//1.提供id值
		Integer empId = 3;
		
		//2.执行根据主键进行的查询
		Employee employee = employeeService.getEmployeeById(empId);
		
		//3.打印结果
		System.out.println(employee);
		
	}

	@Test
	public void testExistsWithPrimaryKey() {
		
		//1.提供主键值
		Integer empId = 33;
		
		//2.执行查询
		boolean exists = employeeService.isExists(empId);
		
		//3.打印结果
		System.out.println(exists);
		
	}

	@Test
	public void testInsert() {
		
		//1.创建实体类对象封装要保存到数据库的数据
		Employee employee = new Employee(null, "emp03", 3000.00, 23);
		
		//2.执行插入操作
		employeeService.saveEmployee(employee);
		
		//3.获取employee对象的主键字段值
		Integer empId = employee.getEmpId();
		System.out.println("empId="+empId);
		
	}

	@Test
	public void testInsertSelective() {
		
		//1.创建实体类对象封装要保存到数据库的数据
		Employee employee = new Employee(null, "emp04", null, 23);
		
		//2.执行插入操作
		employeeService.saveEmployeeSelective(employee);
		
	}

	@Test
	public void testUpdateByPrimaryKey() {
		
	}

	@Test
	public void testUpdateByPrimaryKeySelective() {
		
		//1.创建用于测试的实体类
		Employee employee = new Employee(7, "empNewName", null, null);
		
		//2.执行更新
		employeeService.updateEmployeeSelective(employee);
		
	}

	@Test
	public void testDelete() {
		
		//1.声明实体类变量作为查询条件
		Employee employee = null;
		
		//2.执行删除
		employeeService.removeEmployee(employee);
		
	}

	@Test
	public void testDeleteByPrimaryKey() {
		
		//1.提供主键值
		Integer empId = 13;
		
		//2.执行删除
		employeeService.removeEmployeeById(empId);
		
	}
	
	//==================5 QBC 查询 ========================================
	
	//5.1概念Query By Criteria Criteria 是 Criterion 的复数形式。意思是:规则、标准、准则。
	//在 SQL 语句中相当 于查询条件。
	//QBC 查询是将查询条件通过 Java 对象进行模块化封装。
	@Test
	public void testSelectByExample() {
		
		//目标:WHERE (emp_salary>? AND emp_age<?) OR (emp_salary<? AND emp_age>?)
		//1.创建Example对象
		Example example = new Example(Employee.class);
		
		//***********************
		//i.设置排序信息
		example.orderBy("empSalary").asc().orderBy("empAge").desc();
		
		//ii.设置“去重”
		example.setDistinct(true);
		
		//iii.设置select字段
		example.selectProperties("empName","empSalary");
		
		//***********************
		
		//2.通过Example对象创建Criteria对象
		Criteria criteria01 = example.createCriteria();
		Criteria criteria02 = example.createCriteria();
		
		//3.在两个Criteria对象中分别设置查询条件
		//property参数:实体类的属性名
		//value参数:实体类的属性值
		criteria01.andGreaterThan("empSalary", 3000)
				  .andLessThan("empAge", 25);
		
		criteria02.andLessThan("empSalary", 5000)
				  .andGreaterThan("empAge", 30);
		
		//4.使用OR关键词组装两个Criteria对象
		example.or(criteria02);
		
		//5.执行查询
		List<Employee> empList = employeeService.getEmpListByExample(example);
		
		for (Employee employee : empList) {
			System.out.println(employee);
		}
	}

	@Test
	public void testSelectOneByExample() {
		
	}

	@Test
	public void testSelectCountByExample() {
		
	}

	@Test
	public void testDeleteByExample() {
		
	}

	@Test
	public void testUpdateByExample() {
		
	}

	@Test
	public void testUpdateByExampleSelective() {
		
	}

	@Test
	public void testSelectByExampleAndRowBounds() {
		
	}

	@Test
	public void testSelectByRowBounds() {
		
		int pageNo = 3;
		int pageSize = 5;
		
		int index = (pageNo - 1) * pageSize;
		
		RowBounds rowBounds = new RowBounds(index, pageSize);
		
		List<Employee> empList = employeeService.getEmpListByRowBounds(rowBounds);
		for (Employee employee : empList) {
			System.out.println(employee);
		}
		
	}

}

MapperTest.java

package com.atguigu.mapper.test;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MapperTest {
	
	private ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-context.xml");
	
	@Test
	public void testDataSource() throws SQLException {
		DataSource dataSource = iocContainer.getBean(DataSource.class);
		Connection connection = dataSource.getConnection();
		System.out.println(connection);
	}
	
}

MBG  通用工程 逆向工程

 

 

 

 MBGTest.java


package com.atguigu.shop.test;

import java.io.InputStream;
import java.util.Iterator;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.atguigu.shop.entities.Employee;
import com.atguigu.shop.mappers.EmployeeMapper;

import tk.mybatis.mapper.mapperhelper.MapperHelper;

public class MBGTest {
	
	public static void main(String[] args) {
		
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		
		InputStream inputStream = MBGTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
		
		SqlSessionFactory factory = builder.build(inputStream);
		
		SqlSession session = factory.openSession();
		
		//***********************
		//按照Java方式整合通用Mapper的特殊设置
		//i.创建MapperHelper对象
		MapperHelper mapperHelper = new MapperHelper();
		
		//ii.通过MapperHelper对象对MyBatis原生的Configuration对象进行处理
		Configuration configuration = session.getConfiguration();
		mapperHelper.processConfiguration(configuration);
		
		//***********************
		
		EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
		
		Iterator<Employee> iterator = mapper.selectAll().iterator();
		
		while (iterator.hasNext()) {
			Employee employee = (Employee) iterator.next();
			System.out.println(employee);
		}
		
	}

}

config.properties

# Database connection information
jdbc.driverClass = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/common_mapper
jdbc.user = root
jdbc.password = root

#c3p0
jdbc.maxPoolSize=50
jdbc.minPoolSize=10
jdbc.maxStatements=100
jdbc.testConnection=true

# mapper
mapper.plugin = tk.mybatis.mapper.generator.MapperPlugin
mapper.Mapper = tk.mybatis.mapper.common.Mapper

mybatis-config.xml

<?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="jdbc.properties"/>
	
	<!-- 配置MyBatis运行环境 -->
	<environments default="development">
		<!-- 配置专门用于开发过程的运行环境 -->
		<environment id="development">
			<!-- 配置事务管理器 -->
			<transactionManager type="JDBC"/>
			<!-- 配置数据源 -->
			<dataSource type="POOLED">
				<property name="username" value="${jdbc.user}"/>
				<property name="password" value="${jdbc.password}"/>
				<property name="driver" value="${jdbc.driver}"/>
				<property name="url" value="${jdbc.url}"/>
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<package name="com.atguigu.shop.mappers"/>
	</mappers>

</configuration>

//测试自定义mapper接口

 MyBatchUpdateTest.java

package com.atguigu.mapper.test;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.atguigu.mapper.entities.Employee;
import com.atguigu.mapper.services.EmployeeService;

public class MyBatchUpdateTest {
	//用于功能扩展的接口和实现类
	public static void main(String[] args) {
		
		ClassPathXmlApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-context.xml");
		
		EmployeeService employeeService = iocContainer.getBean(EmployeeService.class);
		
		List<Employee> empList = new ArrayList<>();
		
		empList.add(new Employee(25, "newName01", 111.11, 10));
		empList.add(new Employee(26, "newName02", 222.22, 20));
		empList.add(new Employee(27, "newName03", 333.33, 30));
		
		employeeService.batchUpdateEmp(empList);
		
		iocContainer.close();
	}

}

EmployeeService.java

package com.atguigu.mapper.services;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.atguigu.mapper.entities.Employee;
import com.atguigu.mapper.mappers.EmployeeMapper;

@Service
public class EmployeeService {
	
	@Autowired
	private EmployeeMapper employeeMapper;

	public List<Employee> getAll() {
		return employeeMapper.selectAll();
	}

	public void batchUpdateEmp(List<Employee> empList) {
		employeeMapper.batchUpdate(empList);
	}

}

MyBatchUpdateMapper.java

package com.atguigu.mapper.mine_mappers;

import java.util.List;

import org.apache.ibatis.annotations.UpdateProvider;

public interface MyBatchUpdateMapper<T> {
	
	@UpdateProvider(type=MyBatchUpdateProvider.class, method="dynamicSQL")
	void batchUpdate(List<T> list);

}

MyBatchUpdateProvider.java

package com.atguigu.mapper.mine_mappers;

import java.util.Set;

import org.apache.ibatis.mapping.MappedStatement;

import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;

public class MyBatchUpdateProvider extends MapperTemplate {

	public MyBatchUpdateProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
		super(mapperClass, mapperHelper);
	}
	
	/*
		<foreach collection="list" item="record" separator=";" >
			UPDATE tabple_emp
			<set>
				emp_name=#{record.empName},
				emp_age=#{record.empAge},
				emp_salary=#{record.empSalary},
			</set>
			where emp_id=#{record.empId}
		</foreach>
	 */
	//在类里面需要提供一个和接口同名的方法 batchUpdate
	public String batchUpdate(MappedStatement statement) {
		
		//1.创建StringBuilder用于拼接SQL语句的各个组成部分
		StringBuilder builder = new StringBuilder();
		
		//2.拼接foreach标签
		builder.append("<foreach collection=\"list\" item=\"record\" separator=\";\" >");
		
		//3.获取实体类对应的Class对象
		Class<?> entityClass = super.getEntityClass(statement);
		
		//4.获取实体类在数据库中对应的表名
		String tableName = super.tableName(entityClass);
		
		//5.生成update子句
		String updateClause = SqlHelper.updateTable(entityClass, tableName);
		
		builder.append(updateClause);
		
		builder.append("<set>");
		
		//6.获取所有字段信息
		Set<EntityColumn> columns = EntityHelper.getColumns(entityClass);
		
		String idColumn = null;
		String idHolder = null;
		
		for (EntityColumn entityColumn : columns) {
			
			boolean isPrimaryKey = entityColumn.isId();
			
			//7.判断当前字段是否为主键
			if(isPrimaryKey) {
				
				//8.缓存主键的字段名和字段值
				idColumn = entityColumn.getColumn();
				
				//※返回格式如:#{record.age,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
				idHolder = entityColumn.getColumnHolder("record");
				
			}else {
				
				//9.使用非主键字段拼接SET子句
				String column = entityColumn.getColumn();
				String columnHolder = entityColumn.getColumnHolder("record");
				
				builder.append(column).append("=").append(columnHolder).append(",");
				
			}
			
		}
		
		builder.append("</set>");
		
		//10.使用前面缓存的主键名、主键值拼接where子句
		builder.append("where ").append(idColumn).append("=").append(idHolder);
		
		builder.append("</foreach>");
		
		//11.将拼接好的字符串返回
		return builder.toString();
	}

}

BaseTypeHandler用法

setNonNullParameter

getNullableResult

getNullableResult

getNullableResultgetNullableResult

 TypeHandlerTest.java

package com.atguigu.mapper.test;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.atguigu.mapper.entities.Address;
import com.atguigu.mapper.entities.SeasonEnum;
import com.atguigu.mapper.entities.User;
import com.atguigu.mapper.services.UserService;

public class TypeHandlerTest {
	
	private UserService userService;
	
	{
		userService = new ClassPathXmlApplicationContext("spring-context.xml").getBean(UserService.class);
	}
	
	@Test
	public void testQueryUser() {
		
		Integer userId = 8;
		
		User user = userService.getUserById(userId);
		
		System.out.println(user);
	}
	
	@Test
	public void testSaveUser() {
		
		User user = new User(null, "tom08", new Address("AAA", "BBB", "CCC"), SeasonEnum.AUTUMN);
		
		userService.saveUser(user);
		
	}

}

UserService.java

package com.atguigu.mapper.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.atguigu.mapper.entities.User;
import com.atguigu.mapper.mappers.UserMapper;

@Service
public class UserService {
	
	@Autowired
	private UserMapper userMapper;

	public void saveUser(User user) {
		userMapper.insert(user);
	}

	public User getUserById(Integer userId) {
		return userMapper.selectByPrimaryKey(userId);
	}

}

UserMapper.java

package com.atguigu.mapper.mappers;

import com.atguigu.mapper.entities.User;

import tk.mybatis.mapper.common.Mapper;

public interface UserMapper extends Mapper<User> {

}

AddressTypeHandler.java

package com.atguigu.mapper.handlers;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import com.atguigu.mapper.entities.Address;

public class AddressTypeHandler extends BaseTypeHandler<Address> {
	
	//setNonNullParameter
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, Address address, JdbcType jdbcType)
			throws SQLException {
		
		//1.对address对象进行验证
		if(address == null) {
			return ;
		}
		
		//2.从address对象中取出具体数据
		String province = address.getProvince();
		String city = address.getCity();
		String street = address.getStreet();
		
		//3.拼装成一个字符串
		//规则:各个值之间使用“,”分开
		StringBuilder builder = new StringBuilder();
		builder
			.append(province)
			.append(",")
			.append(city)
			.append(",")
			.append(street);
		
		String parameterValue = builder.toString();
		
		//4.设置参数
		ps.setString(i, parameterValue);
		
	}
	//getNullableResult
	@Override
	public Address getNullableResult(ResultSet rs, String columnName) throws SQLException {
		
		//1.根据字段名从rs对象中获取字段值
		String columnValue = rs.getString(columnName);
		
		//2.验证columnValue是否有效
		if(columnValue == null || columnValue.length() == 0 || !columnValue.contains(",")) {
			return null;
		}
		
		//3.根据“,”对columnValue进行拆分
		String[] split = columnValue.split(",");
		
		//4.从拆分结果数组中获取Address需要的具体数据
		String province = split[0];
		String city = split[1];
		String street = split[2];
		
		//5.根据具体对象组装一个Address对象
		Address address = new Address(province, city, street);
		
		return address;
	}
	
	//getNullableResult
	@Override
	public Address getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		//1.根据字段名从rs对象中获取字段值
		String columnValue = rs.getString(columnIndex);
		
		//2.验证columnValue是否有效
		if(columnValue == null || columnValue.length() == 0 || !columnValue.contains(",")) {
			return null;
		}
		
		//3.根据“,”对columnValue进行拆分
		String[] split = columnValue.split(",");
		
		//4.从拆分结果数组中获取Address需要的具体数据
		String province = split[0];
		String city = split[1];
		String street = split[2];
		
		//5.根据具体对象组装一个Address对象
		Address address = new Address(province, city, street);
		
		return address;
	}
	//getNullableResult
	@Override
	public Address getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		//1.根据字段名从rs对象中获取字段值
		String columnValue = cs.getString(columnIndex);
		
		//2.验证columnValue是否有效
		if(columnValue == null || columnValue.length() == 0 || !columnValue.contains(",")) {
			return null;
		}
		
		//3.根据“,”对columnValue进行拆分
		String[] split = columnValue.split(",");
		
		//4.从拆分结果数组中获取Address需要的具体数据
		String province = split[0];
		String city = split[1];
		String street = split[2];
		
		//5.根据具体对象组装一个Address对象
		Address address = new Address(province, city, street);
		
		return address;
	}

}

User.java

package com.atguigu.mapper.entities;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;

/**
	CREATE TABLE `table_user` (
		`user_id` INT NOT NULL AUTO_INCREMENT,
		`user_name` VARCHAR (100) NULL,
		`address` VARCHAR (100) NULL,
		`season` VARCHAR (100) NULL,
		PRIMARY KEY (`user_id`)
	);
 * @author Lenovo
 *
 */
@Table(name="table_user")
public class User {
	
	@Id
	private Integer userId;
	
	private String userName;
	
	//@ColumnType(typeHandler=AddressTypeHandler.class)
	@Column
	private Address address;
	
	//在枚举类型这里无法使用@ColumnType注解注册MyBatis内置的枚举类型处理器
	//@ColumnType(typeHandler=EnumTypeHandler.class)
	@Column
	private SeasonEnum season;
	
	public User() {
		
	}

	public User(Integer userId, String userName, Address address, SeasonEnum season) {
		super();
		this.userId = userId;
		this.userName = userName;
		this.address = address;
		this.season = season;
	}

	@Override
	public String toString() {
		return "User [userId=" + userId + ", userName=" + userName + ", address=" + address + ", season=" + season
				+ "]";
	}

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public SeasonEnum getSeason() {
		return season;
	}

	public void setSeason(SeasonEnum season) {
		this.season = season;
	}

}

SeasonEnum.java

package com.atguigu.mapper.entities;

public enum SeasonEnum {
	
	SPRING("spring @_@"),SUMMER("summer @_@"),AUTUMN("autumn @_@"),WINTER("winter @_@");
	
	private String seasonName;
	
	private SeasonEnum(String seasonName) {
		this.seasonName = seasonName;
	}
	
	public String getSeasonName() {
		return this.seasonName;
	}
	
	public String toString() {
		return this.seasonName;
	}

}

Address.java


package com.atguigu.mapper.entities;

public class Address {
	
	private String province;
	private String city;
	private String street;
	
	public Address() {
		// TODO Auto-generated constructor stub
	}

	public Address(String province, String city, String street) {
		super();
		this.province = province;
		this.city = city;
		this.street = street;
	}

	@Override
	public String toString() {
		return "Address [province=" + province + ", city=" + city + ", street=" + street + "]";
	}

	public String getProvince() {
		return province;
	}

	public void setProvince(String province) {
		this.province = province;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

}

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值