使用Idea+MyBatisPlus+SpringMVC完成单表操作及分页功能
1. MyBatisPlus简介
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
1.1. 特性
- 无侵入: Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做增强不做改变,引入 Mybatis-Plus 不会对您现有的 Mybatis 构架产生任何影响,而且 MP 支持所有 Mybatis 原生的特性
- **依赖少:**仅仅依赖 Mybatis 以及 Mybatis-Spring
- **损耗小:**启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- **预防Sql注入:**内置 Sql 注入剥离器,有效预防Sql注入攻击
- **通用CRUD操作:**内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- **多种主键策略:**支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题
- **支持热加载:**Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
- **支持ActiveRecord:**支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作
- **支持代码生成:**采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(P.S. 比 Mybatis 官方的 Generator 更加强大!)
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere ) - **支持关键词自动转义:**支持数据库关键词(order、key…)自动转义,还可自定义关键词
- **内置分页插件:**基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询
- **内置性能分析插件:**可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询
- **内置全局拦截插件:**提供全表 delete 、 update 操作智能分析阻断,预防误操作
1.2. 架构原理
2.入门案例
2.1 使用MyBatis-Plus,需要加入两个jar包,如下:
<!--mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
需要注意的地方是,使用Maven加入MyBatis-Plus的jar包,则不需要在配置MyBatis和MyBatis-Spring整合包了,这些MyBatis-Plus会自动维护,避免出现jar冲突。
2.2 整合Spring框架的核心配置
<!--sqlSessionFacotry-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<property name="plugins">
<array>
<!-- 分页插件配置 -->
<bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 乐观锁插件 -->
<bean id="optimisticLockerInterceptor" class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor">
</bean>
<!-- 性能拦截器,兼打印sql,不建议生产环境配置-->
<bean id="performanceInterceptor" class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"/>
</array>
</property>
</bean>
<!-- 定义 MP 全局策略 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 全局ID类型: 0, "数据库ID自增", 1, "用户输入ID", 2, "全局唯一ID", 3, "全局唯一ID"-->
<property name="idType" value="3"/>
<!--主键Sequence-->
<property name="keyGenerator" ref="keyGenerator"/>
<!-- 全局表为下划线命名设置 true -->
<property name="dbColumnUnderline" value="true" />
</bean>
<!-- 配置oracle主键Sequence, 其他类型数据库,请配置相应的类型-->
<bean id="keyGenerator" class="com.baomidou.mybatisplus.incrementer.OracleKeyGenerator"/>
<!-- 配置mybatis 扫描mapper接口的路径, 相当于注解@MapperScan,@MapperScan("com.baomidou.mybatisplus.test.h2.entity.mapper")-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zt.mapper"/>
</bean>
#3. 使用MyBatisPlus完成对单张表(Oracle自带的Dept表)的操作
##3.1使用Idea创建一个简单的MavenWeb项目
具体步骤可以参考我之前的博客JAVA开发使用SSM框架入门案例
##3.2 配置Maven 的pom.xml 所需的jar
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zt</groupId>
<artifactId>mybatisplus-springmvc</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mybatisplus-springmvc Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>5.0.4.RELEASE</spring.version>
<aspectJ.version>1.8.13</aspectJ.version>
<mybatisplus.version>2.2.0</mybatisplus.version>
<oracle.version>11.2.0.1.0</oracle.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.25</slf4j.version>
<c3p0.version>0.9.5.2</c3p0.version>
<servlet.version>3.1.0</servlet.version>
<jstl.version>1.2.5</jstl.version>
<taglibs.version>1.2.5</taglibs.version>
<jackson.version>2.9.4</jackson.version>
<commons.lang3.version>3.7</commons.lang3.version>
<velocity.version>2.0</velocity.version>
</properties>
<dependencies>
<!--spring 基础包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring 事务包 jdbc,tx-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring web mvc 模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring整合的测试包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--AespectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectJ.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectJ.version}</version>
</dependency>
<!--mybatisplus,加入该jar后,就不再需要mybatis-xxx.jar,mybatis-spring-xxx.jar了,它们会以依赖包的形式被自动维护-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<!--oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>${oracle.version}</version>
</dependency>
<!--c3p0数据源-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<!--jstl-->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-jstlel</artifactId>
<version>${jstl.version}</version>
</dependency>
<!--json数据转换包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!--cocommons-lang3-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
</dependencies>
<build>
<finalName>mybatisplus-springmvc</finalName>
<plugins>
<!--配置maven的编译环境,不然mavn模版默认会使用jdk1.5版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
项目jar包部门示例图:
2.3 逆向工程的执行文件完成包路径和数据库的连接配置
在项目工程中,
● 创建一个src/main/java/genterator目录,并设置java目录为源码目录, ● 创建一个src/test/resources目录,并设置resources目录为测试源码目录, 在genterator目录下新建一个GenteratorCode.java文件
GenteratorCode.java文件配置如下:
package genterator;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.*;
/**
* Created by CDHong on 2018/4/6.
*/
public class GenteratorCode {
public static void main(String[] args) throws InterruptedException {
//用来获取mybatis-plus.properties文件的配置信息
final ResourceBundle rb = ResourceBundle.getBundle("mybatis-plus");
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(rb.getString("OutputDir"));
gc.setFileOverride(true);
gc.setActiveRecord(true);
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(true);// XML columList
gc.setAuthor(rb.getString("author"));
// 自定义文件命名,注意 %s 会自动填充表实体属性!
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
gc.setServiceName("I%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setControllerName("%sController");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.ORACLE);
/*dsc.setTypeConvert(new MySqlTypeConvert(){
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
System.out.println("转换类型:" + fieldType);
return super.processTypeConvert(fieldType);
}
});*/
dsc.setDriverName(rb.getString("oracle.driver"));
dsc.setUrl(rb.getString("oracle.url"));
dsc.setUsername(rb.getString("oracle.user"));
dsc.setPassword(rb.getString("oracle.pwd"));
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
// strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
//strategy.setTablePrefix(new String[] { "SYS_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[] {"EMP","DEPT"}); // 需要生成的表
//strategy.setExclude(new String[]{"test"}); // 排除生成的表
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent(rb.getString("parent"));
// pc.setModuleName("tbldept");//模块名称,单独生成模块时使用!!!!!!!!!!!
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("entity");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-rb");
this.setMap(map);
}
};
// 调整 xml 生成目录演示
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirXml")+ "/mybatis/mappers/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 关闭默认 xml 生成,调整生成 至 根目录
TemplateConfig tc = new TemplateConfig();
tc.setXml(null);
mpg.setTemplate(tc);
// 执行生成
mpg.execute();
}
}
```xml
> 文件开始引入了一个外部属性配置文件:
> ● **mybatis-plus.properties:**该文件主要配置要生成的包文件所对应的路径,注释的作者说明,数据库连接等...
>● **mybatis-plus.properties** 属性配置文件文件存放于src/test/resources目录下,文件信息如下:
#此处为本项目src所在路径(代码生成器输出路径),注意一定是当前项目所在的目录哟
OutputDir=D:\IdeaProjects\mybatisplus-springmvc\src\main\java
#mapper.xml SQL映射文件目录
OutputDirXml=D:\IdeaProjects\mybatisplus-springmvc\src\main\resources
#设置作者
author=CDHong
#自定义包路径
parent=com.zt
#数据库连接信息
oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
oracle.user=scott
oracle.pwd=tiger
``
2.4生成项目所需文件
到此逆向工程配置完毕,检查自己数据库是否开启, 对应的数据表是否存在,resouces配置文件信息是否正确,在GenteratorCode.java文件中的引用是否正确,确认无误后,就可以运行GerteratorCode.java文件中的main方法自动生成代码了,执行结果如下:
Controller文件信息
package com.zt.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
/**
* <p>
* 前端控制器
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
@Controller
@RequestMapping("/dept")
public class DeptController {
}
Entity实体文件信息,
通过下面生成的代码我们也可以看出,最好数据库中表和字段的命名使用下划线的形式来完成,不然生成的代码不能实现骆驼命令方式。
package com.zt.entity;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.activerecord.Model;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
public class Dept extends Model<Dept> {
private static final long serialVersionUID = 1L;
@TableId("DEPTNO")
private Integer deptno;
@TableField("DNAME")
private String dname;
@TableField("LOC")
private String loc;
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
protected Serializable pkVal() {
return this.deptno;
}
@Override
public String toString() {
return "Dept{" +
", deptno=" + deptno +
", dname=" + dname +
", loc=" + loc +
"}";
}
}
Mapper接口文件信息
package com.zt.mapper;
import com.zt.entity.Dept;
import com.baomidou.mybatisplus.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
public interface DeptMapper extends BaseMapper<Dept> {
}
Service接口文件信息
package com.zt.service;
import com.zt.entity.Dept;
import com.baomidou.mybatisplus.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
public interface IDeptService extends IService<Dept> {
}
Service实现类文件信息
package com.zt.service.impl;
import com.zt.entity.Dept;
import com.zt.mapper.DeptMapper;
import com.zt.service.IDeptService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {
}
Maper.xml SQL映射文件信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zt.mapper.DeptMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.zt.entity.Dept">
<id column="DEPTNO" property="deptno" />
<result column="DNAME" property="dname" />
<result column="LOC" property="loc" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
DEPTNO AS deptno, DNAME AS dname, LOC AS loc
</sql>
</mapper>
到此项目的逆向工程就介绍完毕,接下来我们就是用生成的这些文件来完成我们的单表操作和分页啦!
3.整合Spring+MyBatisPlus框架
整合Spring框架完成Bean管理,方便对象创建操作,当然MybatisPlus框架是需要Spring的,不然很多东西完成起来比较麻烦.框架整合,推荐使用xml配置的形式来完成,在这里只需要整合Spring和MyBatisPlus框架,web层使用Spring的Web模块来完成。
在src/main/resources目录下新建一个spring目录,用于存放Spring框架的配置文件。
3.1持久层(spring+mybatisplus)配置
在src/main/resouces/spring中新建两个spring的配置文件: ● spring-mybatis-plus.xml 用于持久层的配置(dao,service,数据源,事务...) ● spring-mvc.xml 用于视图显示和控制的配置(controller,exception,上传下载...)
先配置spring-mybatis-plus.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: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.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--加载c3p0.properties-->
<context:property-placeholder location="classpath:datasource.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="${oracle.driver}"/>
<property name="jdbcUrl" value="${oracle.url}"/>
<property name="user" value="${oracle.user}"/>
<property name="password" value="${oracle.pwd}"/>
<property name="initialPoolSize" value="${c3p0.initPoolSize}"/>
<property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
<property name="minPoolSize" value="${c3p0.minPoolSize}"/>
<property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>
<property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>
<property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
</bean>
<!--sqlSessionFacotry-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<property name="plugins">
<array>
<!-- 分页插件配置 -->
<bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 乐观锁插件 -->
<bean id="optimisticLockerInterceptor" class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor">
</bean>
<!-- 性能拦截器,兼打印sql,不建议生产环境配置-->
<bean id="performanceInterceptor" class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"/>
</array>
</property>
</bean>
<!-- 定义 MP 全局策略 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 全局ID类型: 0, "数据库ID自增", 1, "用户输入ID", 2, "全局唯一ID", 3, "全局唯一ID"-->
<property name="idType" value="3"/>
<!--主键Sequence-->
<property name="keyGenerator" ref="keyGenerator"/>
<!-- 全局表为下划线命名设置 true -->
<property name="dbColumnUnderline" value="true" />
</bean>
<!-- 配置oracle主键Sequence, 其他类型数据库,请配置相应的类型-->
<bean id="keyGenerator" class="com.baomidou.mybatisplus.incrementer.OracleKeyGenerator"/>
<!-- 配置mybatis 扫描mapper接口的路径, 相当于注解@MapperScan,@MapperScan("com.baomidou.mybatisplus.test.h2.entity.mapper")-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zt.mapper"/>
</bean>
<!--配置事务管理-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--使用注解完成事务管理,注册-->
<tx:annotation-driven />
<!--把DAO交给Service-->
<context:component-scan base-package="com.zt.service.impl" />
</beans>
在该配置文件中,需要引入两个属性配置文件:
● datasource.properties 配置文件:放置于src/main/resouces/
目录下,主要用于数据库连接和C3P0数据源的常用配置。
● mybatis-config.xml 配置文件:放置于src/main/resouces/mybatis/
目录下,主要用于mybatis的常用配置(别名,缓存,懒加载,骆驼命名等…),主要还是为了和spring的配置区分开,不要全部都在一个文件中去配置。
● 如果要查看项目的运行流程和数据库执行SQL,还需要加入一个配置文件。log4j.properties.注意这个文件需放在src/mian/resouces下且文件名也不能更改,当然想更改也可以,只是要加入一些配置去做修改,这里就不详细说了。
目录结构如下:
datasource.properties属性配置文件信息如下
oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
oracle.user=scott
oracle.pwd=tiger
c3p0.initPoolSize = 5
c3p0.maxPoolSize = 500
c3p0.minPoolSize = 5
c3p0.acquireIncrement = 10
c3p0.maxIdleTime = 60000
c3p0.checkoutTimeout = 60000
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>
<settings>
<!--Mybaits的日志操作,使用log4j完成,这样避免sql语句无法打印-->
<setting name="logImpl" value="log4j"/>
<!--开启骆驼命名-->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<!--别名配置-->
<typeAliases>
<package name="com.zt.entity" />
</typeAliases>
</configuration>
log4j.properties属性配置文件信息如下:
### Global logging configuration
log4j.rootLogger=Debug, stdout
### Uncomment for MyBatis logging
log4j.logger.org.apache.ibatis=ERROR
### Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
log4j.appender.lastEventSavedAppender=org.apache.ibatis.session.AutoMappingUnknownColumnBehaviorTest$LastEventSavedAppender
至此,持久层的所有配置都完毕了,接下来就是使用Junit来完成测试了。
3.2使用junit4完成单表CUID及分页测试
在src/test/java目录下新建一个新目录junit,在该目录下新建一个测试类DeptTest.java,用于完成测试操作。
package junit;
import com.zt.entity.Dept;
import com.zt.service.IDeptService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
/**
* Created by CDHong on 2018/4/6.
*/
@ContextConfiguration("classpath:spring/spring-mybatis-plus.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class DeptTest {
@Autowired private IDeptService deptService;
/**
* 在做保存的时候,可以自己手动添加主键,也可以使用序列来完成,
* 相应的配置需要在spring-mybatis-plus.xml配置文件中找到以下两句配置
* <property name="idType" value="2"/>
* <property name="keyGenerator" ref="keyGenerator"/>
* 如果是手动添加主键,则idType的value值改为1,keyGenerator不需要配置
* 如果是使用序列,则使用默认配置,除此之外需要在对应的实体类上添加如下注解:
* @KeySequence(value = "seq_dept",clazz = Integer.class)
* value:是要使用的序列名称 clazz是接受的值类型,默认是Long类型,这个结合自己实体字段类型来更改
*/
@Test
public void testSave(){
Dept dept = new Dept();
dept.setDname("科技部");
dept.setLoc("重庆");
boolean flg = deptService.insert(dept);
System.out.println(flg);
}
@Test
public void testUpdate(){
//先查询部门,再根据需求修改
Dept dept = deptService.selectById(63);
//设置要修改的信息
dept.setDname("市场部");
dept.setLoc("渝北");
boolean flg = deptService.updateById(dept);
System.out.println(flg);
}
@Test
public void testFindAll(){
List<Dept> deptList = deptService.selectList(null);
for(Dept dept:deptList){
System.out.println(dept);
}
}
@Test
public void testDel(){
boolean flg = deptService.deleteById(62);
System.out.println(flg);
}
@Test
public void testPageInfo(){
//Page(pageIndex,pageSize)
Page page = new Page(1,2);
//查询条件实体
EntityWrapper<Dept> ew = new EntityWrapper<>();
ew.like("dname","A").orderBy("deptno");
Page<Dept> deptPage = deptService.selectPage(page, ew);
System.out.println("总页数:"+deptPage.getTotal());
System.out.println("当前页码:"+deptPage.getCurrent());
System.out.println("每页显示条数:"+deptPage.getSize());
System.out.println("当前页数据:"+deptPage.getRecords());
}
}
这里重点说一下保存操作,Oracle数据库的数据新增,没有自增操作,想要实现自增,需要借助序列来完成,所以在做添加操作的时候,需要指定是用序列还是手动输入,通过配置来指定,除此之外还需要在对应的实体上用注解指定要使用的序列名称。
实体注解,指定序列和类型:如下配置:
执行保存操作打印的SQL信息:
执行分页操作打印的SQL信息:
3.3视图层(springmvc)配置
完成视图解析配置,静态资源处理以及字符编码设置.在src/main/resources/spring目录下,找到spring-mvc.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: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="com.zt.controller" />
<!-- 编码配置 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<mvc:annotation-driven />
<!---静态资源处理-->
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
以上配置需要添加两个文件用于项目架构完善:resources(静态资源文件:css,js,image,前端框架等),pages(前端用于显示的静态页面:jsp,html,前端模版等),两个文件当存放与外界不可访问的安全目录WEB-INF目录下。
3.4配置web.xml文件启动配置
配置web.xml,因为maven模板自动生成的web.xml版本较低(2.3)。我们需要通过idea工具重新生成一个版本较高的文件(3.1),操作如图所示:
生成完毕后,在web.xml加入如下代码,完成请求字符编码处理(spring提供的过滤器),持久层配置监听启动和前端MVC中央处理器设置以及欢迎界面设置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--字符编码过滤器-->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--加载Spring IOC容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mybatis-plus.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--加载spring mvc 模块-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/WEB-INF/pages/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
3.5jsp编写和数据显示
以上设置完毕后就是和浏览器做交互了,先在resources目录下引入我们需要的用到的前端框架layui,以及脚本文件js,并在js目录下创建一个dept.js备用,然后在pages目录下新建一个index.jsp做web.xml中配置的欢迎界面,再新建一个dept文件夹,用于存储dept操作所需的页面。并在其中新建一个list.jsp用于后端的响应页面。
在index.jsp中录入一个超链接用于访问后端控制器,测试是否可以正常启动访问
**index.jsp页面**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basePath%>"/>
<title>主界面</title>
</head>
<body>
<a href="dept/index">显示部门信息</a>
</body>
</html>
list.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basePath%>" />
<title>部门管理</title>
</head>
<body>
部门管理列表
</body>
</html>
接着在系统提供的DeptController.java文件中创建一个方法接收index.jsp的请求
package com.zt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 前端控制器
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
@Controller
@RequestMapping("/dept")
public class DeptController {
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index(){
return "dept/list";
}
}
接下来配置我们的Web服务器Tomcat,部署项目,完成测试。配置Tomcat和项目部署可以参考:JAVA开发使用SSM框架入门案例
部署完毕后,启动服务器,打开浏览器输入请求地址:localhost,可以看到如下界面表示没有问题。
当然点击连接也可以访问list.jsp页面。
3.6部门表CUID功能实现
剩下的就是部门表的添加,删除,修改以及分页查询,当然这些功能方法,Mybatis-Plus都帮我们完成了,我们只需要实现相应的逻辑和页面的编写即可,这里使用我们的页面是使用Layui框架来完成的,具体用法请参考经典模块化前端框架
逻辑就不说了,我直接贴一下控制器代码和jsp,js代码
目录架构
JSP页面:
list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basePath%>" />
<title>部门管理</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="resources/layui/css/layui.css">
</head>
<body>
<blockquote class="layui-elem-quote">
<form action="" class="layui-form">
<div class="layui-input-inline">
<input type="text" name="search" required lay-verify="required" placeholder="请输入查询条件" autocomplete="off" class="layui-input"/>
</div>
<div class="layui-input-inline">
<a href="javascript:;" class="layui-btn" lay-submit lay-filter="search-btn">查询</a>
<a href="javascript:;" class="layui-btn layui-btn-normal add-btn">添加部门</a>
</div>
</form>
</blockquote>
<table id="deptList" lay-filter="dept-list"></table>
<script type="text/javascript" src="resources/layui/layui.js"></script>
<script type="text/javascript" src="resources/js/dept.js" ></script>
<script type="text/html" id="dept-tool">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
</body>
</html>
add-edit.jsp页面,这是添加和编辑公用页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<base href="<%=basePath%>"/>
<title>添加部门</title>
<link rel="stylesheet" href="resources/layui/css/layui.css">
<style>
.sys-add-edit{ padding-top: 25px;text-align: center; }
.sys-input-size{width: 380px}
</style>
</head>
<body class="layui-container sys-add-edit">
<form class="layui-form">
<c:if test="${!empty dept.deptno}">
<div class="layui-form-item">
<div class="layui-form-label">部门编号:</div>
<div class="layui-input-block">
<input class="layui-input layui-disabled sys-input-size" name="deptno" readonly value="${dept.deptno}" />
</div>
</div>
</c:if>
<div class="layui-form-item">
<div class="layui-form-label">部门名称:</div>
<div class="layui-input-block">
<input class="layui-input sys-input-size" placeholder="请输入部门名称" required lay-verify="required" name="dname" value="${dept.dname}" />
</div>
</div>
<div class="layui-form-item">
<div class="layui-form-label">部门地址:</div>
<div class="layui-input-block">
<input class="layui-input sys-input-size" placeholder="请输入部门地址" required lay-verify="required" name="loc" value="${dept.loc}" />
</div>
</div>
<div class="layui-form-item">
<c:choose>
<c:when test="${!empty dept.deptno}">
<button class="layui-btn" lay-submit lay-filter="edit-submit">修改</button>
</c:when>
<c:otherwise>
<button class="layui-btn" lay-submit lay-filter="add-submit">添加</button>
</c:otherwise>
</c:choose>
<input type="reset" class="layui-btn layui-btn-normal" value="重置" />
</div>
</form>
<script type="text/javascript" src="resources/layui/layui.js"></script>
<script type="text/javascript" src="resources/js/dept.js" ></script>
</body>
</html>
对应以上两个页面的js代码:
js/dept.js
/**
* Created by CDHong on 2018/4/7.
*/
layui.use(["form","layer","jquery","table"],function(){
var form = layui.form,
layer = layui.layer,
$ = layui.jquery,
table = layui.table;
//设置全局默认参数
table.set({
elem:"#deptList",
url:"dept/list",
method:"post",
//even:true, //隔行变色
limits:[10,15,20],
height: 'full-150',
page:{ limit:10}, //开启分页,并设置每页显示的条数
cols:[[
{checkbox: true},
{field: 'deptno', title: '部门编号', width:180, sort: true, align: 'center'},
{field: 'dname', title: '部门名称', sort: true},
{field: 'loc', title: '部门地址'},
{fixed: 'right',title: '操作', width:150, align:'center', toolbar: '#dept-tool'}
]],
text:{
none:'没有查询到符合条件的数据'
}
});
//初始化表格数据
var rootTable = table.render();
//查询
form.on("submit(search-btn)",function(data){
table.render({
where:data.field
});
return false;
});
//编辑和修改通用弹出层
function layerOpen(title,param){
layer.open({
type:2,
title:title,
content:"dept/add-edit/"+param,
skin:"layui-layer-molv",
area: ['600px', '300px'],
anim: 1,
cancel: function(){
table.render();
}
});
}
//添加部门弹出层
$(".add-btn").click(function(){
layerOpen("添加部门",-1);
});
//删除,添加和编辑的通用方法
function sendAjax(url,info){
$.ajax({
url:url,
method:"post",
data:info,
success:function(){
layer.msg("执行成功!");
//var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
//parent.layer.close(index); //再执行关闭
},
error:function(){
layer.msg("执行失败!");
}
});
}
//添加部门
form.on('submit(add-submit)',function(data){
sendAjax("dept/add-edit",data.field);
return false;
});
//修改部门
form.on("submit(edit-submit)",function(data){
sendAjax("dept/add-edit",data.field);
return false;
});
//监听工具条
table.on('tool(dept-list)',function(obj){
var lay_event = obj.event; //获得 lay-event 对应的值
var data = obj.data; //获得当前行数据
//var tr = obj.tr; //获得当前行 tr 的DOM对象
if(lay_event == 'edit'){
layerOpen("编辑部门",data.deptno);
}else if(lay_event == 'del'){
layer.confirm('你确定要删除【'+data.dname+'】部门吗?',{icon:3,title:"删除提示",skin:"layui-layer-molv"},function(index){
sendAjax("dept/del/"+data.deptno);
layer.close(index);
table.render();
});
}
});
});
控制器代码:DeptController.java
package com.zt.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.entity.Dept;
import com.zt.entity.vo.LayerJson;
import com.zt.service.IDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 前端控制器
* </p>
*
* @author CDHong
* @since 2018-04-06
*/
@Controller
@RequestMapping("/dept")
public class DeptController {
@Autowired private IDeptService deptService;
@RequestMapping(value = "/add-edit/{id}",method = RequestMethod.GET)
public String addOrEdit(@PathVariable Integer id,Model model){
if(id!=-1){
Dept dept = deptService.selectById(id);
model.addAttribute("dept",dept);
}
return "dept/add-edit";
}
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index(){
return "dept/list";
}
/**
* 使用Layui table完成分页功能
* @param pageIndex Layui table 默认提交当前页码的key 是page
* @param pageSize Layui table 默认提交每页显示条数的key 是limit
* @param search 查询条件
* @return 返回自己组装符合Layui table格式的Json数据
* @throws JsonProcessingException
*/
@ResponseBody
@RequestMapping(value = "/list",method = RequestMethod.POST)
public String list(@RequestParam(value = "page",defaultValue = "1") Integer pageIndex, @RequestParam(value = "limit" , defaultValue = "10") Integer pageSize, String search) throws JsonProcessingException {
//查询页码和每页显示的条数
Page page = new Page(pageIndex,pageSize);
//查询条件
EntityWrapper<Dept> ew = new EntityWrapper<>();
ew.orderBy("deptno").or().like("deptno",search).or().like("dname",search).or().like("loc",search);
//根据查询条件查询符合的数据
Page<Dept> mapPage = deptService.selectPage(page, ew);
//这里需要自定义LayerJson类来组装JSON对象数据,主要是前端是用了Layui的table模块,该模块的请求数据需要对应的格式,
//在这里我们建立一个符合格式的vo类来完成
LayerJson layerJson = LayerJson.getInstance(mapPage.getRecords(),mapPage.getTotal());
//转为JSON字符串
return new ObjectMapper().writeValueAsString(layerJson);
}
@RequestMapping(value = "/add-edit",method = RequestMethod.POST)
public ResponseEntity addOrEdit(Dept dept){
boolean flg = deptService.insertOrUpdate(dept);
if(flg){
return new ResponseEntity(HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
@RequestMapping(value = "/del/{id}",method = RequestMethod.POST)
public ResponseEntity del(@PathVariable Integer id){
boolean flg = deptService.deleteById(id);
if(flg){
return new ResponseEntity(HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
LayerJson类,用于转化和Layui table模块对接的数据格式,代码如下:
package com.zt.entity.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.http.HttpStatus;
/**
* Created by CDHong on 2018/4/7.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class LayerJson {
private Integer code; //状态码
private Object data; //返回的数据
private long count; //总条数
public LayerJson(Object data, long count) {
this.code = 0; //layer table 默认正常返回状态码
this.data = data;
this.count = count;
}
public static LayerJson getInstance(Object data, long count){
return new LayerJson(data,count);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}
对应的结构图:
项目截图:部门管理首页
项目截图:添加部门
项目截图:修改部门
项目截图:删除部门
项目截图:模糊查询
项目截图:查询没有输入条件提示
到此整个项目讲解完毕,如需源码可以到这里下载,因为CSDN博客不再支持附件上传,只能通过另外途径给大家提供源码项目源码