【MyBatis】spring整合mybatis教程(详细易懂)

目录

一、引言

1、Spring整合MyBatis的目的是?

二、Spring与MyBatis集成

1、导入pom依赖及插件

1.1、导入依赖

?1.2、导入插件

2、配置文件

generatorConfig.xml

jdbc.properties

log4j2.xml

spring-mybatis.xml

spring-context.xml

生成model、mapper

3、整合测试

1、建立Bookbiz、BookBizImpl

2、创建测试类

3、实体类的更改

[三、Spring Aop集成PageHelper插件](#三、Spring Aop集成PageHelper插件)

1、回顾之前

2、优化


一、引言

1、Spring整合MyBatis的目的是?

将两个框架结合起来,以实现更好的开发体验和效果。Spring提供了一种轻量级的容器和依赖注入的机制,可以简化应用程序的配置和管理。而MyBatis是一个优秀的持久层框架,可以方便地进行数据库操作。通过整合Spring和MyBatis,可以充分发挥它们各自的优势,提高开发效率和代码质量。

二、Spring与MyBatis集成

【注意!!!】整合的时候我们要导入我们的依赖、配置文件及测试是否整合成功

  1. **pom依赖:**spring、mybatis、logger、mysql、mybatis-spring、...、junit、spring-test
  2. **配置文件:**spring-context.xml、spring-mybatis.xml、jdbc.properties、generateConfig.xml、log4j.xml
  3. 测试:
    1. 根据表生成对应的实体类、mapper接口、mapper文件。
    2. 测试类标记为spring测试类,会用注解标记,就代表每一个测试方法,都会加载spring的上下文

1、导入pom依赖及插件

1.1、导入依赖
复制代码
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>

    <!--添加jar包依赖-->
    <!--1.spring 5.0.2.RELEASE相关-->
    <spring.version>5.0.2.RELEASE</spring.version>
    <!--2.mybatis相关-->
    <mybatis.version>3.4.5</mybatis.version>
    <!--mysql-->
    <mysql.version>5.1.44</mysql.version>
    <!--pagehelper分页jar依赖-->
    <pagehelper.version>5.1.2</pagehelper.version>
    <!--mybatis与spring集成jar依赖-->
    <mybatis.spring.version>1.3.1</mybatis.spring.version>
    <!--3.dbcp2连接池相关 druid-->
    <commons.dbcp2.version>2.1.1</commons.dbcp2.version>
    <commons.pool2.version>2.4.3</commons.pool2.version>
    <!--4.log日志相关-->
    <log4j2.version>2.9.1</log4j2.version>
    <!--5.其他-->
    <junit.version>4.12</junit.version>
    <servlet.version>4.0.0</servlet.version>
    <lombok.version>1.18.2</lombok.version>
</properties>


<dependencies>
    <!--1.spring相关-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!--2.mybatis相关-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!--pagehelper分页插件jar包依赖-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>${pagehelper.version}</version>
    </dependency>
    <!--mybatis与spring集成jar包依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>${mybatis.spring.version}</version>
    </dependency>

    <!--3.dbcp2连接池相关-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>${commons.dbcp2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>${commons.pool2.version}</version>
    </dependency>

    <!--4.log日志相关依赖-->
    <!--核心log4j2jar包-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <!--web工程需要包含log4j-web,非web工程不需要-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-web</artifactId>
        <version>${log4j2.version}</version>
    </dependency>

    <!--5.其他-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>${servlet.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>

</dependencies>

①数据库连接池是什么?

会初始化N个数据库链接对象,一般在10个,当需要用户请求操作数据库时候,那么就会直接在数据库连接池中获取链接,用完放回连接池中。

常见的数据库连接池有:dbcp2druidc3p0.

②lombok是什么?

可以更加便捷的使用实体类

复制代码
<resources>
    <!--解决mybatis-generator-maven-plugin运行时没有将XxxMapper.xml文件放入target文件夹的问题-->
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
    </resource>
    <!--解决mybatis-generator-maven-plugin运行时没有将jdbc.properites文件放入target文件夹的问题-->
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>jdbc.properties</include>
            <include>*.xml</include>
        </includes>
    </resource>
</resources>
1.2、导入插件
复制代码
<plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <dependencies>
                    <!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>${mysql.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>

2、配置文件

generatorConfig.xml
复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
    <!-- 引入配置文件 -->
    <properties resource="jdbc.properties"/>

    <!--指定数据库jdbc驱动jar包的位置 maven里面 -->
    <classPathEntry
            location="D:\zking App\mvn_repository\mysql\mysql-connector-java\5.1.44\mysql-connector-java-5.1.44.jar"/>

    <!-- 一个数据库一个context -->
    <context id="infoGuardian">
        <!-- 注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true"/><!-- 是否取消注释 -->
            <property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳 -->
        </commentGenerator>

        <!-- jdbc连接 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>

        <!-- 类型转换 -->
        <javaTypeResolver>
            <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 01 指定javaBean生成的位置 -->
        <!-- targetPackage:指定生成的model生成所在的包名 -->
        <!-- targetProject:指定在该项目下所在的路径  -->
        <javaModelGenerator targetProject="src/main/java" targetPackage="com.tgq.model">
            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对model添加构造函数 -->
            <property name="constructorBased" value="true"/>
            <!-- 是否针对string类型的字段在set的时候进行trim调用 -->
            <property name="trimStrings" value="false"/>
            <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>

        <!-- 02 指定sql映射文件生成的位置 -->
        <sqlMapGenerator targetProject="src/main/java" targetPackage="com.tgq.mapper">
            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 03 生成XxxMapper接口 -->
        <!-- type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象 -->
        <!-- type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象 -->
        <!-- type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口 -->
        <javaClientGenerator targetProject="src/main/java" targetPackage="com.tgq.mapper" type="XMLMAPPER">
            <!-- 是否在当前路径下新加一层schema,false路径com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 配置表信息 -->
        <!-- schema即为数据库名 -->
        <!-- tableName为对应的数据库表 -->
        <!-- domainObjectName是要生成的实体类 -->
        <!-- enable*ByExample是否生成 example类 -->
        <!--<table schema="" tableName="t_book" domainObjectName="Book"-->
        <!--enableCountByExample="false" enableDeleteByExample="false"-->
        <!--enableSelectByExample="false" enableUpdateByExample="false">-->
        <!--&lt;!&ndash; 忽略列,不生成bean 字段 &ndash;&gt;-->
        <!--&lt;!&ndash; <ignoreColumn column="FRED" /> &ndash;&gt;-->
        <!--&lt;!&ndash; 指定列的java数据类型 &ndash;&gt;-->
        <!--&lt;!&ndash; <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> &ndash;&gt;-->
        <!--</table>-->

        <table schema="" tableName="t_mvc_Book" domainObjectName="Book"
               enableCountByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" enableUpdateByExample="false">
            <!-- 忽略列,不生成bean 字段 -->
            <!-- <ignoreColumn column="FRED" /> -->
            <!-- 指定列的java数据类型 -->
            <!-- <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> -->
        </table>

    </context>
</generatorConfiguration>

这里是自己本地路径的MySQL的jar包,是需要更改的,路径赋值后也需要再加上

复制代码
    <!--指定数据库jdbc驱动jar包的位置 maven里面 -->
    <classPathEntry
            location="D:\zking App\mvn_repository\mysql\mysql-connector-java\5.1.44\mysql-connector-java-5.1.44.jar"/>
jdbc.properties

数据库的连接对象

复制代码
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
log4j2.xml
复制代码
<?xml version="1.0" encoding="UTF-8"?>

<!-- status : 指定log4j本身的打印日志的级别.ALL< Trace < DEBUG < INFO < WARN < ERROR
	< FATAL < OFF。 monitorInterval : 用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s. -->
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <!-- 配置日志文件输出目录 ${sys:user.home} -->
        <Property name="LOG_HOME">/root/workspace/lucenedemo/logs</Property>
        <property name="ERROR_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/error</property>
        <property name="WARN_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/warn</property>
        <property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} - %msg%n</property>
    </Properties>

    <Appenders>
        <!--这个输出控制台的配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="trace" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <!-- 输出日志的格式 -->
            <!-- %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间 %p : 日志输出格式 %c : logger的名称
                %m : 日志内容,即 logger.info("message") %n : 换行符 %C : Java类名 %L : 日志输出所在行数 %M
                : 日志输出所在方法名 hostName : 本地机器名 hostAddress : 本地ip地址 -->
            <PatternLayout pattern="${PATTERN}" />
        </Console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
        <!--append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
        <File name="log" fileName="logs/test.log" append="false">
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size, 则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
        <RollingFile name="RollingFileInfo" fileName="${LOG_HOME}/info.log"
                     filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="info" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <!-- 基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。 modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am. -->
                <!-- 关键点在于 filePattern后的日期格式,以及TimeBasedTriggeringPolicy的interval, 日期格式精确到哪一位,interval也精确到哪一个单位 -->
                <!-- log4j2的按天分日志文件 : info-%d{yyyy-MM-dd}-%i.log -->
                <TimeBasedTriggeringPolicy interval="1"
                                           modulate="true" />
                <!-- SizeBasedTriggeringPolicy:Policies子节点, 基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小. -->
                <!-- <SizeBasedTriggeringPolicy size="2 kB" /> -->
            </Policies>
        </RollingFile>

        <RollingFile name="RollingFileWarn" fileName="${WARN_LOG_FILE_NAME}/warn.log"
                     filePattern="${WARN_LOG_FILE_NAME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="2 kB" />
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20" />
        </RollingFile>

        <RollingFile name="RollingFileError" fileName="${ERROR_LOG_FILE_NAME}/error.log"
                     filePattern="${ERROR_LOG_FILE_NAME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <!-- log4j2的按分钟 分日志文件 : warn-%d{yyyy-MM-dd-HH-mm}-%i.log -->
                <TimeBasedTriggeringPolicy interval="1"
                                           modulate="true" />
                <!-- <SizeBasedTriggeringPolicy size="10 MB" /> -->
            </Policies>
        </RollingFile>

    </Appenders>

    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
    <Loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息 -->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>

        <!-- 第三方日志系统 -->
        <logger name="org.springframework" level="ERROR" />
        <logger name="org.hibernate" level="ERROR" />
        <logger name="org.apache.struts2" level="ERROR" />
        <logger name="com.opensymphony.xwork2" level="ERROR" />
        <logger name="org.jboss" level="ERROR" />


        <!-- 配置日志的根节点 -->
        <root level="all">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
            <appender-ref ref="RollingFileWarn" />
            <appender-ref ref="RollingFileError" />
        </root>

    </Loggers>

</Configuration>
spring-mybatis.xml
  1. 扫描所有JavaBean,将对应的组件加载到spring的上下文
  2. 配置session连接工厂
  3. 配置mapper扫描接口
  4. 配置事务管理器
  5. 配置aop自动代理
复制代码
<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--1. 注解式开发 -->
    <!-- 注解驱动 -->
    <context:annotation-config/>
    <!-- 用注解方式注入bean,并指定查找范围:com.javaxl.ssm及子子孙孙包-->
    <context:component-scan base-package="com.tgq"/>

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!--初始连接数-->
        <property name="initialSize" value="10"/>
        <!--最大活动连接数-->
        <property name="maxTotal" value="100"/>
        <!--最大空闲连接数-->
        <property name="maxIdle" value="50"/>
        <!--最小空闲连接数-->
        <property name="minIdle" value="10"/>
        <!--设置为-1时,如果没有可用连接,连接池会一直无限期等待,直到获取到连接为止。-->
        <!--如果设置为N(毫秒),则连接池会等待N毫秒,等待不到,则抛出异常-->
        <property name="maxWaitMillis" value="-1"/>
    </bean>

    <!--4. spring和MyBatis整合 -->
    <!--1) 创建sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 自动扫描XxxMapping.xml文件,**任意路径 -->
        <property name="mapperLocations" value="classpath*:com/tgq/**/mapper/*.xml"/>
        <!-- 指定别名 -->
        <property name="typeAliasesPackage" value="com/javaxl/ssm/**/model"/>
        <!--配置pagehelper插件-->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=mysql
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <!--2) 自动扫描com/javaxl/ssm/**/mapper下的所有XxxMapper接口(其实就是DAO接口),并实现这些接口,-->
    <!--   即可直接在程序中使用dao接口,不用再获取sqlsession对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--basePackage 属性是映射器接口文件的包路径。-->
        <!--你可以使用分号或逗号 作为分隔符设置多于一个的包路径-->
        <property name="basePackage" value="com/tgq/**/mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <aop:aspectj-autoproxy/>
</beans>

注意自己的包名路径,如果不更改后面测试会报错

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--    spring与mybatis整合的配置文件加载spring的上下文-->
    <import resource="classpath:spring-mybatis.xml"></import>



</beans>
生成model、mapper

选中对应的项目,依次选中生成

我们在生成的实体类上面添加**@Repository**,@Repository就相当于****

3、整合测试

1、建立BookbizBookBizImpl

一个接口和一个接口实现类

把我们的生成的BookMapper里面的方法复制到我们新建的BookBiz里面

复制代码
package com.tgq.biz;

import com.tgq.model.Book;

/**
 * @软件包名 com.tgq.biz
 * @用户 tgq
 * @create 2023-08-25 下午4:46
 * @注释说明:
 */
public interface BookBiz {
    int deleteByPrimaryKey(Integer bid);

    int insert(Book record);

    int insertSelective(Book record);

    Book selectByPrimaryKey(Integer bid);

    int updateByPrimaryKeySelective(Book record);

    int updateByPrimaryKey(Book record);
}


package com.tgq.biz.impl;

import com.tgq.biz.BookBiz;
import com.tgq.mapper.BookMapper;
import com.tgq.model.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @软件包名 com.tgq.biz.impl
 * @用户 tgq
 * @create 2023-08-25 下午4:49
 * @注释说明:
 */
@Service//仓库的意思
public class BookBizImpl implements BookBiz {

    @Autowired//相当于get、set
    private BookMapper bookBiz;

    @Override
    public int deleteByPrimaryKey(Integer bid) {
        return bookBiz.deleteByPrimaryKey(bid);
    }

    @Override
    public int insert(Book record) {
        return bookBiz.insert(record);
    }

    @Override
    public int insertSelective(Book record) {
        return bookBiz.insertSelective(record);
    }

    @Override
    public Book selectByPrimaryKey(Integer bid) {
        return bookBiz.selectByPrimaryKey(bid);
    }

    @Override
    public int updateByPrimaryKeySelective(Book record) {
        return bookBiz.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(Book record) {
        return bookBiz.updateByPrimaryKey(record);
    }
}
2、创建测试类

创建BookBizImpl测试类

我们调用一个测试方法进行测试

复制代码
package com.tgq.biz.impl;

import com.tgq.biz.BookBiz;
import org.junit.After;
import org.junit.Before;
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;

/**
 * @软件包名 com.tgq.biz.impl
 * @用户 tgq
 * @create 2023-08-25 下午4:56
 * @注释说明:
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-context.xml"})
public class BookBizImplTest {

    @Autowired//相当于get、set
    private BookBiz bookBiz;

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void deleteByPrimaryKey() {
    }

    @Test
    public void insert() {
    }

    @Test
    public void insertSelective() {
    }

    @Test
    public void selectByPrimaryKey() {
        System.out.println(this.bookBiz.selectByPrimaryKey(60));
    }

    @Test
    public void updateByPrimaryKeySelective() {
    }

    @Test
    public void updateByPrimaryKey() {
    }
}

测试结果

3、实体类的更改

我们的实体类创建属性的时候我写get、set等方法,过于麻烦,但是我们有一个lombok,可以节约掉这些。

1、没有lombok的实体类

复制代码
package com.tgq.model;

public class Book {
    private Integer bid;

    private String bname;

    private Float price;

    public Book(Integer bid, String bname, Float price) {
        this.bid = bid;
        this.bname = bname;
        this.price = price;
    }

    public Book() {
        super();
    }

    public Integer getBid() {
        return bid;
    }

    public void setBid(Integer bid) {
        this.bid = bid;
    }

    public String getBname() {
        return bname;
    }

    public void setBname(String bname) {
        this.bname = bname;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }
}

2、有lombok的实体类

复制代码
package com.tgq.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//get、set、tostring
@Data
//有参构造器
@AllArgsConstructor
//无参构造器
@NoArgsConstructor
public class Book {
    private Integer bid;

    private String bname;

    private Float price;

}

这样看过去就节约了很多的代码

当然使用方法是一样的

三、Spring Aop集成PageHelper插件

1、回顾之前

回顾之前我们用的是插件,或者插件和自己写的分页类。

例如:

  1. 配置xml和生成的接口方法

    复制代码
        <select id="selectPager" resultType="com.tgq.model.Book" parameterType="com.tgq.model.Book">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
            <where>
                <if test="bname != null">
                    and bname like concat('%',#{bname},'%')
                </if>
            </where>
        </select>
    
    
    List<Book> selectPager(Book book);
  2. 实现接口和接口实现类

    复制代码
        List<Book> selectPager(Book book, PageBean pageBean);
    
        @Override
        public List<Book> selectPager(Book book, PageBean pageBean) {
            if (pageBean != null && pageBean.isPagination())
                PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
            List<Book> books = bookBiz.selectPager(book);
            if (pageBean != null && pageBean.isPagination()) {
                PageInfo<Book> info = new PageInfo<>(books);
                pageBean.setTotal((int) info.getTotal());
            }
            return books;
        }
  3. 生成测试方法并进行测试

    复制代码
        @Test
        public void selectPager() {
            Book book = new Book();
            PageBean pageBean = new PageBean();
            pageBean.setPage(2);
            pageBean.setRows(30);
            book.setBname("圣墟");
            this.bookBiz.selectPager(book, pageBean);
        }

    测试结果

2、优化

如何优化我们前面写的代码呢?

复制代码
//        if (pageBean != null && pageBean.isPagination())
//            PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
//        List<Book> books = bookBiz.selectPager(book);
//        if (pageBean != null && pageBean.isPagination()) {
//            PageInfo<Book> info = new PageInfo<>(books);
//            pageBean.setTotal((int) info.getTotal());
//        }
//        return books;

需要用到环绕通知,编写切面类。
所以我们编写一个切面包和PagerAspect

  1. 在前面写的接口实现类selectPager方法进行修改

    复制代码
    package com.tgq.biz.impl;
    
    import com.tgq.biz.BookBiz;
    import com.tgq.mapper.BookMapper;
    import com.tgq.model.Book;
    import com.tgq.utils.PageBean;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /**
     * @软件包名 com.tgq.biz.impl
     * @用户 tgq
     * @create 2023-08-25 下午4:49
     * @注释说明:
     */
    @Service//仓库的意思
    public class BookBizImpl implements BookBiz {
    
        @Autowired//相当于get、set
        private BookMapper bookBiz;
    
    
        @Override
        public List<Book> selectPager(Book book, PageBean pageBean) {
    
            return bookBiz.selectPager(book);
        }
    }
  2. 在切面类PagerAspect里面编写方法,该有的注释也在里面,我这里就不一一的解释了。

    复制代码
    package com.tgq.aspect;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.tgq.utils.PageBean;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    /**
     * @软件包名 com.tgq.aspect
     * @用户 tgq
     * @create 2023-08-25 下午9:26
     * @注释说明:
     */
    @Aspect //代表当前类为切面类
    @Component //代表该类交给spring进行管理
    public class PagerAspect {
        /**
         * * *..*biz.*Pager(..)
         * * : 任意返回值
         * *..: 任意版本 不限层级
         * *biz :以biz结尾的接口/类
         * *Pager :以pager结尾的方法
         * .. :任意参数
         * <p>
         * 符合条件,就是目标或者目标方法
         *
         * @param args
         * @return
         * @throws Throwable
         */
        @Around("execution(* *..*biz.*Pager(..))")
        public Object invoke(ProceedingJoinPoint args) throws Throwable {
    //        获取目标方法中的所有参数
            Object[] params = args.getArgs();
            PageBean pageBean = null;
            for (Object param : params) {
                if (param instanceof PageBean) {
    //                强转
                    pageBean = (PageBean) param;
                    break;
                }
            }
    
            if (pageBean != null && pageBean.isPagination())
                PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
    //执行目标方法
            Object list = args.proceed(params);
    
            if (null != pageBean && pageBean.isPagination()) {
                PageInfo pageInfo = new PageInfo((List) list);
                pageBean.setTotal((int) pageInfo.getTotal());
            }
            return list;
        }
    
    
    }
  3. 还是运行上面一样的测试类的方法

    复制代码
        @Test
        public void selectPager() {
            Book book = new Book();
            PageBean pageBean = new PageBean();
            pageBean.setPage(2);
            pageBean.setRows(30);
            book.setBname("圣墟");
            this.bookBiz.selectPager(book, pageBean);
        }

    测试结果

感谢支持!!!

相关推荐
gechunlian8810 分钟前
Spring Boot中的404错误:原因、影响及处理策略
java·spring boot·后端
岁岁种桃花儿21 分钟前
AI超级智能开发系列从入门到上天第四篇:AI应用方案设计
java·服务器·开发语言
架构师沉默1 小时前
Java 终于有自己的 AI Agent 框架了?
java·后端·架构
程序员爱酸奶1 小时前
ThreadLocal内存泄漏深度解析
java
givemeacar1 小时前
Spring Boot中集成MyBatis操作数据库详细教程
数据库·spring boot·mybatis
czlczl200209251 小时前
JVM创建对象过程
java·开发语言
一直都在5721 小时前
线程间的通信
java·jvm
GIOTTO情2 小时前
Infoseek危机公关全链路技术解析:基于近期热点舆情的落地实践
java
我是人✓2 小时前
从零入门 Servlet:JavaWeb 核心组件的实操与理解
java·servlet
lay_liu2 小时前
Spring Boot 自动配置
java·spring boot·后端