CREATE DATABASE mp;
USE mp;
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1),
age INT
);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('tom','[email protected]',1,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('jerry','[email protected]',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('black','[email protected]',1,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('white','[email protected]',0,35);
public class Employee{
private Integer id;
private String lastName;
private String email;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
pom.xml配置
<dependencies>
<!-- mybatis-plus会自动维护我们的mybatis以及mybatis-spring相关的依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
</dependencies>
加入mybatis全局配置文件
<?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>
加入db.properties 连接配置信息
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mp
jdbc.username = root
jdbc.password = 123456
加入Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!-- 加载配置属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置SessionFactory -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="org.sy.library.entity.*"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- MyBatis 动态扫描 -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mp.mapper"/>
</bean>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 基于注解的事务管理-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>
测试spring-mybatis环境
public class TestMP {
private ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
@Test
public void testDataSource() throws SQLException {
DataSource ds = ioc.getBean("dataSource",DataSource.class);
System.out.println(ds);
Connection connection = ds.getConnection();
System.out.println(connection);
}
}
public interface EmployeeMapper extends BaseMapper<Employee> {
}
测试
@Test
public void testInsert(){
Employee employee = new Employee();
employee.setLastName("MP");
employee.setEmail("[email protected]");
employee.setGender(1);
employee.setAge(22);
Integer insert = employeeMapper.insert(employee);
System.out.println(insert);
}
出现异常:
org.mybatis.spring.MyBatisSystemException: nested exception isorg.apache.ibatis.reflection.ReflectionException: Could not setproperty ‘id’ of ‘class com.mp.beans.Employee’ with value ‘1274261141571284993’ Cause: java.lang.IllegalArgumentException: argument type mismatch
其原因是mybatis-plus在为我们自动生成主键时出现错误,此时需要用到注解
再次运行该异常消失,但又出现了新异常
很明显,字面意思就是找不到mp数据库中employee表,我们的表名是tbl_employee,此时便用到了另一个注解
再次运行测试即可成功
MP全局配置策略
在application.xml可配置mybatis-plus全局配置策略
<!-- MyBatisPlus 全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 2.3版本后默认值为true,因此不写也可-->
<property name="dbColumnUnderline" value="true"></property>
<!--全局的主键策略-->
<!-- 相当于@TableId(value = "id",type = IdType.AUTO)-->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置-->
<!-- 相当于@TableName(value = "tbl_+实体类名(小写)")-->
<property name="tablePrefix" value="tbl_"></property>
</bean>
将其注入到SQLSessionFactoryBean中
将Employee中id上的@TableId
与@TableName
注解注释掉后,测试插入依然可以
还有一点需要注意,在mybatis中如果需要获取返回插入数据的主键值,还需要在mapper.xml中进行属性配置,而mybatis-plus则不需要任何配置,他会自动返回插入数据的主键值;
在测试插入方法加上两行代码;获取返回的Id值
测试insertAllColumn方法(3.0版本后弃用,了解即可)
insert方法有一个小问题,就是在插入的时候,他会扫描那些属性赋了值,在插入的时候只会对你赋值的属性进行操作,insertAllColumn解决的就是这一问题,无论你赋没赋值,他都会对所有属性进行操作
Employee employee = new Employee();
employee.setLastName("MP");
employee.setEmail("[email protected]");
employeeMapper.insert(employee);
//当使用insert方法插入,插入语句如下
insert into tbl_employee(last_name,email) values('MP','[email protected]');
//当使用insertAllColumn方法插入,插入语句如下
insert into tbl_employee(last_name,email,gender,age) values('MP','[email protected]',null,null);
注意:二者只在SQL语句上有区别,插入结果是没有区别的
@Test
public void testUpdate(){
Employee employee = new Employee();
employee.setId(5);
employee.setLastName("QQQ");
employee.setEmail("[email protected]");
employee.setGender(3);
employee.setAge(25);
Integer update = employeeMapper.updateById(employee);
System.out.println(update);
}
@Test
public void testSelect(){
//1.通过Id查询
Employee employee = employeeMapper.selectById(1);
System.out.println(employee);
//2.通过多个列查询;只能查询一条记录,有多条记录会报错
Employee employee2 = new Employee();
employee2.setId(5);
employee2.setLastName("QQQ");
Employee employee1 = employeeMapper.selectOne(employee2);
System.out.println(employee1);
//3.通过多个id查询
List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(2);
idList.add(3);
List<Employee> employees = employeeMapper.selectBatchIds(idList);
System.out.println(Arrays.asList(employees));
//4.通过Map封装条件查询
Map<String,Object> map = new HashMap<>();
map.put("last_name","MP");
map.put("gender",1);
List<Employee> employees1 = employeeMapper.selectByMap(map);
System.out.println(Arrays.asList(employees1));
//5.分页查询:查询第3页,每页2条记录
List<Employee> employees2 = employeeMapper.selectPage(new Page<>(3, 2), null);
System.out.println(Arrays.asList(employees2));
}
@Test
public void testDelete(){
//1.根据Id删除
Integer integer = employeeMapper.deleteById(10);
System.out.println(integer);
//2.根据多个条件删除
Map<String,Object> map = new HashMap<>();
map.put("id",5);
map.put("last_name","QQQ");
Integer integer1 = employeeMapper.deleteByMap(map);
System.out.println(integer1);
//3.删除多个
List<Integer> idList = new ArrayList<>();
idList.add(6);
idList.add(7);
idList.add(8);
Integer integer3 = employeeMapper.deleteBatchIds(idList);
System.out.println(integer3);
}
注意:(3.0之后拆分为AbstractWrapper、QueryWrapper、UpdateWrapper以及使用 Wrapper 自定义SQL,详情可查官网)
@Test
public void testEntityWrapperSelect(){
//需要在分页查询Employee表中,年龄在18~50之间且性别为男性,姓名为MP的所有用户
List<Employee> age = employeeMapper.selectPage(new Page<Employee>(1, 2),
new EntityWrapper<Employee>()
.between("age", 18, 50)
.eq("gender",1)
.eq("last_name","MP"));
System.out.println(Arrays.asList(age));
}
@Test
public void testEntityWrapperSelect2(){
//查询在tbl_employee表中,性别为女且名字中带有“e”或者邮箱中带有“o”
List<Employee> employees = employeeMapper.selectList(new EntityWrapper<Employee>()
.eq("gender", 0)
.like("last_name", "e")
//.or() // WHERE (gender = ? AND last_name LIKE ? OR email LIKE ?)
.orNew() //WHERE (gender = ? AND last_name LIKE ?) OR (email LIKE ?)
.like("email", "o"));
System.out.println(Arrays.asList(employees));
}
@Test
public void testEntityWrapperSelect3(){
Employee employee = new Employee();
employee.setLastName("www");
employee.setEmail("[email protected]");
employee.setAge(29);
Integer update = employeeMapper.update(employee,
new EntityWrapper<Employee>().eq("last_name", "MP1"));
System.out.println(update);
}
@Test
public void testEntityWrapperSelect4(){
Integer delete = employeeMapper.delete(new EntityWrapper<Employee>().eq("last_name", "www"));
System.out.println(delete);
}
ActiveRecord(活动记录),一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录
仅仅需要让实体类继承Model类且实现主键指定方法,即可开始AR之旅
@Test
public void testARInsert(){
Employee employee = new Employee();
employee.setLastName("苍井空");
employee.setEmail("[email protected]");
employee.setAge(35);
employee.setGender(0);
boolean insert = employee.insert();
System.out.println(insert);
}
@Test
public void testARInsert(){
Employee employee = new Employee();
employee.setLastName("苍井空");
employee.setEmail("[email protected]");
employee.setAge(35);
employee.setGender(0);
boolean insert = employee.insert();
System.out.println(insert);
}
@Test
public void testARSelect(){
//1.根据Id查询
Employee employee = new Employee();
Employee employee1 = employee.selectById(15);
System.out.println(employee1);
//2.查询全部
List<Employee> employees = employee.selectAll();
System.out.println(Arrays.asList(employees));
//3.模糊查询
List<Employee> employees1 = employee.selectList(new EntityWrapper<Employee>().like("last_name", "M"));
System.out.println(Arrays.asList(employees1));
//4.查个数
int gender = employee.selectCount(new EntityWrapper<Employee>().eq("gender", 0));
System.out.println(gender);
}
@Test
public void testARDelete(){
Employee employee = new Employee();
boolean b = employee.deleteById(15);
System.out.println(b);
boolean delete = employee.delete(new EntityWrapper<Employee>().eq("last_name", "MP"));
System.out.println(delete);
}
@Test
public void testARSelectPage(){
List<Employee> employees = employeeMapper.selectPage(new Page<Employee>(2, 1),
new EntityWrapper<Employee>().like("email", "e"));
System.out.println(employees);
}
<!-- MP的代码生成器默认使用的是Apache的Velocity模板-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<!-- 加入slf4j,查看日志输出信息-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
/**
* 代码生成器
*/
@Test
public void test(){
//1.全局配置
GlobalConfig config = new GlobalConfig();
config.setActiveRecord(true) //是否支持AR模式
.setAuthor("东方老赢")//作者
.setOutputDir("F:\\test")//生成路径
.setFileOverride(true)//文件覆盖
.setIdType(IdType.AUTO)//主键策略
.setServiceName("%sService")//设置生成的service接口的名字的首字母(默认为I)
.setBaseResultMap(true)//XML ResultMap
.setBaseColumnList(true);//XML columList
//2.数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL)//设置数据库类型
.setDriverName("com.mysql.jdbc.Driver")
.setUsername("root")
.setPassword("123456")
.setUrl("jdbc:mysql://127.0.0.1:3306/mp");
//3.策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setCapitalMode(true)// 全局大写命名 ORACLE 注意
.setDbColumnUnderline(true)//指定表名、字段名是否使用下划线
.setTablePrefix("tbl_")// 此处可以修改为您的表前缀
.setNaming(NamingStrategy.underline_to_camel)// 表名生成策略
.setInclude("tbl_employee" ); // 需要生成的表
//4.包名策略配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.mp.velocity")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("beans")
.setXml("mapper");
//5.整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config);
ag.setStrategy(strategy);
ag.setDataSource(dsc);
ag.setPackageInfo(pc);
//执行
ag.execute();
}
运行测试成功后会自动打开文件位置
在Mapper接口中定义相关的CRUD方法
public interface EmployeeMapper extends BaseMapper<Employee> {
int deleteAll();
}
在扩展AutoSqlInjector inject方法,实现Mapper接口中方法要注入的SQL
public class MySqlInjector extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
Class<?> modelClass, TableInfo table) {
/* 添加一个自定义方法 */
deleteAllUser(mapperClass, modelClass, table);
}
public void deleteAllUser(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
/* 执行 SQL ,动态 SQL 参考类 SqlMethod */
String sql = "delete from " + table.getTableName();
/* mapper 接口方法名一致 */
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addMappedStatement(mapperClass, method, sqlSource, SqlCommandType.DELETE, Integer.class);
}
}
在MP全局策略中,配置自定义注入器
<!-- 定义 MP 全局策略,安装集成文档部分结合 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
.....
<!-- 自定义注入 deleteAll 方法 -->
<property name="sqlInjector" ref="mySqlInjector" />
</bean>
<!-- 自定义注入器 -->
<bean id="mySqlInjector" class="com.baomidou.test.MySqlInjector" />
实现元对象处理器接口: com.baomidou.mybatisplus.mapper.IMetaObjectHandler
注解填充字段 @TableField(.. fill = FieldFill.INSERT)
生成器策略部分也可以配置!
public class User {
// 注意!这里需要标记为填充字段
@TableField(.. fill = FieldFill.INSERT)
private String fillField;
....
}
自定义实现类 MyMetaObjectHandler
/** 自定义填充公共 name 字段 */
public class MyMetaObjectHandler extends MetaObjectHandler {
/**
* 测试 user 表 name 字段为空自动填充
*/
public void insertFill(MetaObject metaObject) {
// 更多查看源码测试用例
System.out.println("*************************");
System.out.println("insert fill");
System.out.println("*************************");
// 测试下划线
Object testType = getFieldValByName("testType", metaObject);//mybatis-plus版本2.0.9+
System.out.println("testType=" + testType);
if (testType == null) {
setFieldValByName("testType", 3, metaObject);//mybatis-plus版本2.0.9+
}
}
@Override
public void updateFill(MetaObject metaObject) {
//更新填充
System.out.println("*************************");
System.out.println("update fill");
System.out.println("*************************");
//mybatis-plus版本2.0.9+
setFieldValByName("lastUpdatedDt", new Timestamp(System.currentTimeMillis()), metaObject);
}
}
spring 启动注入 MyMetaObjectHandler 配置
<!-- MyBatis SqlSessionFactoryBean 配置 -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="globalConfig" ref="globalConfig"></property>
</bean>
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 公共字段填充处理器 -->
<property name="metaObjectHandler" ref="myMetaObjectHandler" />
</bean>
<!-- 自定义处理器 -->
<bean id="myMetaObjectHandler" class="com.baomidou.test.MyMetaObjectHandler" />