Spring+SpringMVC+Mybatis SSM集成

SSM集成(超详细)Spring+SpringMVC+Mybatis

一.导入依赖

包含了logo4j 日志 Spring +SpringMVC+Mybatis(带分页)+generator代码生成器

 <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>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- spring版本号 -->
    <spring.version>4.1.2.RELEASE</spring.version>
    <!-- mybatis版本号 -->
    <mybatis.version>3.2.1</mybatis.version>
    <!-- log4j日志文件管理包版本 -->
    <slf4j.version>1.7.2</slf4j.version>
    <log4j.version>1.2.17</log4j.version>
    <!-- jackson包版本 -->
    <jackson.version>2.5.0</jackson.version>
  </properties>
  <dependencies>
    <!--JUnit-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--Spring核心-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</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-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
    </dependency>
    <!--SpringMVC-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--aop依赖包-->
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.6.8</version>
    </dependency>
    <!--文件上传-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.2</version>
    </dependency>
    <!--jackson-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <!--数据库连接池-->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.2</version>
    </dependency>
    <dependency>
      <groupId>commons-pool</groupId>
      <artifactId>commons-pool</artifactId>
      <version>1.5.3</version>
    </dependency>
    <!--Mybatis集成-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.0</version>
    </dependency>
    <!--log4j-->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
    </dependency>
    <!--slf4j-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <!--数据库连接驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.46</version>
    </dependency>
    <!-- JSTL标签类 -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>
    <!--mybatis分页插件-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.0.1</version>
    </dependency>
  </dependencies>
<!--  <build>
    <finalName>crm</finalName>
    <plugins>
      &lt;!&ndash;代码生成器插件&ndash;&gt;
      <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.2</version>
        <configuration> &lt;!&ndash;自定义代码生成器的路径&ndash;&gt; &lt;!&ndash;<configurationFile>yourLocation/mybatis-generator-config.xml</configurationFile>&ndash;&gt;
          <verbose>true</verbose>
          <overwrite>true</overwrite>
        </configuration>
      </plugin>
    </plugins>
  </build>-->
  <build>
    <plugins>
      <!--mybatis的generator插件-->
      <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.2</version>
        <configuration>
          <verbose>true</verbose>
          <!-- 代表mybatis generator生成的内容所需数据库驱动,注意不要覆盖已有的内容 -->
          <overwrite>false</overwrite>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

二.使用generator

使用generator插件根据数据库表生成对应domain,Mapper接口 以及映射文件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>
    <!--
    	classPathEntry:可以配置多个,也不配置
    	数据库驱动:这里找到相应的驱动jar包就可以了(注:不同数据库的jar不一样)
    		location:里面的是路径(也可以直接写绝对路径 -> 如:E:\mybatis\mysql-connector-java-5.1.26-bin.jar)
    -->
    <classPathEntry   location="D:/Program Files/repository/mysql/mysql-connector-java/5.1.26/mysql-connector-java-5.1.26.jar"/>
    <!--
    	context:用于生成一组对象的环境(至少配置1个,可以配置多个)
    	id:表达唯一的名称
    	targetRuntime:用于指定生成的代码的运行环境(MyBatis3/MyBatis3Simple)
    		MyBatis3:默认值
    		MyBatis3Simple:不会生成与Example(案例)相关的方法
    -->
    <context id="DB2Tables"   targetRuntime="MyBatis3Simple" >
        <!--
            用于配置如果生成注释信息(最多可以配置一下)
            suppressAllComments:阻止生成注释 ,默认为false
            suppressDate:阻止生成的注释 时间戳,默认为false
            addRemarkComments:注释是否添加数据库表的备注信息,默认为false
         -->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--
        	这个应该比较清楚,配置连接数据库的基本信息
        -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql:///mybatis"
                        userId="root" password="root">
        </jdbcConnection>
        <!--
        	用于指定JDBC类型和Java类型如何转换,最多可以配置一个
        	forceBigDecimals:控制是否强制将DECIMAL和NUMERIC类型的JDBC字段转换成Java类型的 BigDecimal
        					 默认为false,一般不需要配置
        -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!--
        	javaModelGenerator:用来控制生成的实体类
	        	targetPackage:生成Model类存放位置(包名)
	        	targetProject:指定目标项目路径(根目录)
        		对应的子属性:
	        		trimStrings:判断是否对数据库查询结果进行trim操作(默认false)
        -->
        <javaModelGenerator targetPackage="cn.leilei.myssm.domain" targetProject="src/main/java">
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!--
        	sqlMapGenerator:生成映射文件存放位置(Mapper.xml文件)
        		targetPackage:生成SQL映射文件(XML文件)在哪个包中
        		targetProject:指定目标项目路径(根目录)
        -->
        <sqlMapGenerator targetPackage="cn.leilei.myssm.mapper" targetProject="src/main/resources">
        </sqlMapGenerator>

        <!--
        	javaClientGenerator:Java客户端生成器(生成Dao/Mapper的接口)
        						该 标签可选(最多配置一个),如果不配置,就不会生成Mapper接口
        		type:选择客户端代码生成器
        			MyBatis3
        				ANNOTATEDMAPPER:基于注解的Mapper接口,不会有对应的XML映射文件
        				MIXEDMAPPER:XML和注解混合形式
        				XMLMAPPER:所有方法都在XML中(接口调用依赖XML)
        			MyBatis3Simple
        				ANNOTATEDMAPPER:基于注解的Mapper接口,不会有对应的XML映射文件
        				XMLMAPPER:所有方法都在XML中(接口调用依赖XML)
        		targetPackage:生成Mapper接口存放的包名
        		targetProject:指定目标项目路径
        -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="cn.leilei.myssm.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!--
        	table:生成对应表及类名
	        	tableName:对应表名(注:%代表所有)
	        	domainObjectName:对应的类名
        		generatedKey:主键自增的id字段(针对当前 数据库配置MySQL)
        -->
        <table tableName="productdir" domainObjectName="Productdir">
            <generatedKey column="id" sqlStatement="MySql" />
        </table>
    </context>
</generatorConfiguration>


三.配置文件

(1)连接数据库 jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis
jdbc.username=root
jdbc.password=root

(2)日志配置

想要打印日志还可以做日志配置

#rootLogger :全局打印策略 ,
# 打印级别 ERROR , 日志级别从打印少到多排序:   ERROR , WARN , INFO , DEBUG ,TRACE
#stdout :这个地方配置的是日志打印方式,和具体格式
log4j.rootLogger=ERROR, stdout
#log4j.rootLogger=NONE

# logger :局部打印,一般指定我们自己的包名
#把左边包名改成你自己的包名
log4j.logger.cn.leilei=DEBUG

#具体的打印方式:使用控制台输入日志
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#指定打印的布局: PatternLayout 指的是自定义打印格式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

#自定义的日志打印格式
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

(3)Spring配置 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
       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
">
    <!--
        1.db.properties   2.引入db.properties
    3.创建数据源(dataSource)
    4.配置一个Bean:SqlSessionFactory
    5.配置Mapper  6.domain,mapper:查询测试
    7.完成Service
    8.完成Controller(集成SpringMVC)
    -->
<!--將servic层交给spring管理-->
    <context:component-scan base-package="cn.leilei.myssm.service"/>
    <!--引入jdbc.properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--配置连接池 四大金刚-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    <!--.配置一个Bean:SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
            <!--mybatis主文件-->
       <!-- <property name="configLocation" value="classpath:mybatis-config.xml"></property>-->
        <!--XML的映射-->
        <property name="mapperLocations" value="classpath:cn/leilei/myssm/mapper/*.xml" />
        <!--为所有相应的包中的类取别名-->
        <property name="typeAliasesPackage" value="cn.leilei.myssm.domain" />
        <!--配置一个拦截器(分页插件):注意一下版本问题(就可以不用单独再设置一个mybatis-config.xml了,如果其中配置了分页则必须注释掉-->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>helperDialect=mysql</value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
    <!--一劳永逸的方案:直接创建所有的映射器mapper-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.leilei.myssm.mapper" />
    </bean>
    <!--我们需要配置一个事务管理器
    以前学习JPA ,是有一个类JpaTransactionManager的事务对象
    mybatis用的是:DataSourceTransactionManager
-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--配置标签支持事务-->
    <tx:annotation-driven transaction-manager="transactionManager" />

</beans>

(4)MVC配置 applicationContext-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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
       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
">
    <!--扫描Controller层-->
    <context:component-scan base-package="cn.leilei.myssm.web.controller"/>
    <!--开启MVC注解支持-->
    <mvc:annotation-driven/>
    <!--开启静态资源放行-->
    <mvc:default-servlet-handler/>
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!--上传解析器-->
    <!--文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为2000000 -->
        <property name="maxUploadSize">
            <value>2000000</value>
        </property>
    </bean>

</beans>

(4)配置web.xml

xml表头可以在tomcat 安装目录下conf 包下web.xml中拷贝 最好与其版本一致

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


  <!--读取Spring的核心配置文件-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>


  <!--设置spring全局监听-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--配置核心控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--SpringMVC的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContest-mvc.xml</param-value>
    </init-param>
    <!--随着tomcat启动而启动 设置启动优先级-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--解决Post提交乱码问题-->
  <filter>
    <filter-name>characterEncodingFilter</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>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

四.Mapper接口以及映射文件

(1)product

public interface ProductMapper {
    //根據id查询一个
    Product findOne(Long id);

    //根据m名字查询一个
    Product findOneByname(String name);

    //高级查询 根据条件
    List<Product> findAllByquery(MyQuery query);

    //删除多条数据
    void moreDelete(List<Long> ids);

    //修改
    void update(Product product);

    //批量新增
    void moreAdd(List<Product> products);


    //多对一嵌套结果
    List<Product> selectAll();
    //多对一嵌套查询
    List<Product> selectAll2();

    //一对多额外sql语句
    List<Product> selectAllBydirid();
}
(1.1)product的映射文件
<?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="cn.leilei.myssm.mapper.ProductMapper" >
  <!--配置手动映射-->
  <resultMap id="ProductResultMap" type="cn.leilei.myssm.domain.Product" >
    <id column="id" property="id"  />
    <result column="product_name" property="productName"  />
    <result column="dir_id" property="dirId" />
    <result column="sale_price" property="salePrice" />
<!--多对一嵌套结果-->
    <association property="productdir" javaType="cn.leilei.myssm.domain.Productdir" columnPrefix="d_">
      <id column="id" property="id"/>
      <result column="dir_name" property="dirName"/>
      <result column="parent_id" property="parentId"/>
    </association>
    <!--多對一嵌套查詢-->
    <association property="productdir" javaType="cn.leilei.myssm.domain.Productdir" column="dir_id"
                 select="cn.leilei.myssm.mapper.ProductdirMapper.findAll"/>
  </resultMap>



  <select id="findOne" resultMap="ProductResultMap">
    SELECT id,product_name,dir_id,sale_price from product WHERE id=#{id};
  </select>
  <select id="findOneByname" resultMap="ProductResultMap">
    SELECT id,product_name,dir_id,sale_price FROM product WHERE product_name=#{productName};
  </select>
  <!--高級查询 根据条件-->
  <select id="findAllByquery" resultMap="ProductResultMap">
    SELECT id,product_name,dir_id,sale_price FROM product
    <where>
      <if test="productName!=null">
        AND product_name LIKE CONCAT("%",#{productName},"%")
      </if>
      <if test="minsalePrice!=null">
        and sale_price>=#{minsalePrice}
      </if>
      <if test="maxsalePrice!=null">
        and sale_price &lt;=#{maxsalePrice}
      </if>
    </where>
  </select>

  <!--删除多条数据-->
  <delete id="moreDelete" parameterType="list">
    DELETE FROM product WHERE id IN
    <foreach collection="list" item="id" open="(" close=")" separator=",">
      #{id}
    </foreach>
  </delete>

  <!--修改数据,未传入的字段不做修改-->
  <update id="update" parameterType="Product">
    UPDATE product
    <set>
      <if test="productName!=null">
        product_name=#{productName},
      </if>
      <if test="dirId!=null">
        dir_id=#{dirId},
      </if>
      <if test="salePrice!=null">
        sale_price=#{salePrice},
      </if>
    </set>
    where id=#{id};
  </update>

  <!--批量新增-->
  <insert id="moreAdd">
    INSERT INTO product(product_name, dir_id, sale_price) VALUES
    <foreach collection="list" separator="," item="product">
      (#{product.productName},#{product.dirId},#{product.salePrice})
    </foreach>
  </insert>

  <!--多对一嵌套结果-->
  <select id="selectAll" resultMap="ProductResultMap">
    SELECT
    p.id,p.product_name,p.dir_id,p.sale_price,
    d.id as d_id ,d.dir_name as d_dir_name,d.parent_id as d_parent_id
    FROM product p JOIN productdir d ON p.dir_id=d.id;

  </select>

  <!--多对一嵌套查询-->
  <select id="selectAll2" resultMap="ProductResultMap">
    SELECT
    p.id,p.product_name,p.dir_id,p.sale_price
    FROM product p
  </select>

  <!--一对多额外sql语句-->
  <select id="selectAllBydirid" resultMap="ProductResultMap">
    SELECT * from product WHERE dir_id=#{id};
  </select>
</mapper>

(2)productdir

mapper接口

public interface ProductdirMapper {
    //多对一嵌套查询额外sql
    List<Productdir> findAll();

    //一對多嵌套结果
    List<Productdir> selectAll();

    //一對多嵌套查询
    List<Productdir> selectAll2();
}
(2.1)productdir的映射文件
<?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="cn.leilei.myssm.mapper.ProductdirMapper" >
  <resultMap id="ProductdirResultMap" type="cn.leilei.myssm.domain.Productdir" >
    <id column="id" property="id" jdbcType="BIGINT" />
    <result column="dir_name" property="dirName" />
    <result column="parent_id" property="parentId" />

    <!--一对多嵌套结果使用-->
    <collection property="productList" ofType="cn.leilei.myssm.domain.Product" columnPrefix="p_">
      <id column="id" property="id"/>
      <result column="product_name" property="productName"/>
      <result column="dir_id" property="dirId"/>
      <result column="sale_price" property="salePrice"/>
    </collection>
    <!--一對多嵌套查询使用-->
    <collection property="productList" ofType="cn.leilei.myssm.domain.Product" column="id"
                select="cn.leilei.myssm.mapper.ProductMapper.selectAllBydirid"/>
  </resultMap>

    <!--多對一嵌套查询额外sql-->
    <select id="findAll" resultMap="ProductdirResultMap">
        SELECT * from productdir WHERE id=#{dirId};
    </select>
  <!--一对多嵌套结果-->
  <select id="selectAll" resultMap="ProductdirResultMap">
    SELECT d.id,d.dir_name,d.parent_id,p.id as p_id,p.product_name as p_product_name,p.dir_id as p_dir_id,
    p.sale_price as p_sale_price FROM product p JOIN productdir d ON p.dir_id=d.id;
  </select>
  <!--一对多嵌套查询-->
  <select id="selectAll2" resultMap="ProductdirResultMap">
    SELECT d.id,d.dir_name,d.parent_id FROM productdir d;
  </select>
</mapper>

(3)定义的查询类

package cn.leilei.myssm.query;

public class MyQuery {
    private String productName;    //产品名
    private Double maxsalePrice;   //最高价格
    private Double minsalePrice;   //最低价格

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Double getMaxsalePrice() {
        return maxsalePrice;
    }

    public void setMaxsalePrice(Double maxsalePrice) {
        this.maxsalePrice = maxsalePrice;
    }

    public Double getMinsalePrice() {
        return minsalePrice;
    }

    public void setMinsalePrice(Double minsalePrice) {
        this.minsalePrice = minsalePrice;
    }
}

(4)小总结

(1)关联对象多方/一方,标签使用
(1.1)association /collection

关联对象为一方则使用association 关联对象类型用javaType, 关联对象为多方则使用collection 关联对象类型使用ofType

(1.2)where标签

动态拼接条件使用and多条件查询 自动根据条件 使用或者忽略and 在写时每一个条件之前带上and即可,会帮我们解决

    SELECT id,product_name,dir_id,sale_price FROM product
    <where>
      <if test="productName!=null">
        AND product_name LIKE CONCAT("%",#{productName},"%")
      </if>
      <if test="minsalePrice!=null">
        and sale_price>=#{minsalePrice}
      </if>
      <if test="maxsalePrice!=null">
        and sale_price &lt;=#{maxsalePrice}
      </if>
    </where>
(1.3)foreach标签
做批量操作时进行循环,例如传过来id集合  使用for循环 进行解决   open 以什么开始 close以什么结尾,separator以什么间隔  比方传来过{1,2,3,4}  使用此循环后为 (1,2,3,4,) 可在批量删除或者查询使用
<foreach collection="list" item="id" open="(" close=")" separator=",">
      #{id}
</foreach>
----------------------------------------------------------------------
传入对象结合{a,b,c,d}  可在新增修改时刻进行操作 (a.productName,a.dirId,a.salePrice),(b.productName,b.dirId,b.salePrice)
<foreach collection="list" separator="," item="product">
 (#{product.productName},#{product.dirId},#{product.salePrice})
</foreach>
(2)嵌套结果 关联对象查询的方式之一

嵌套结果查询,就是只使用一条sql语句 将几张表使用join关系关联起来 在自己映射的Map中添加关联对象映射信息,例如 product 与productdir为多对一关系

在Product表中需要配置productdir类型字段

private Productdir productdir;

sql语句使用join将表进行关联 返回类型指向手动映射文件名字

  <!--多对一嵌套结果-->
  <select id="selectAll" resultMap="ProductResultMap">
    SELECT
    p.id,p.product_name,p.dir_id,p.sale_price,
    d.id as d_id ,d.dir_name as d_dir_name,d.parent_id as d_parent_id
    FROM product p JOIN productdir d ON p.dir_id=d.id;

  </select>

那么在手动映射map中就要加入对象的关系映射

(1)方式一
  <!--配置手动映射-->
  <resultMap id="ProductResultMap" type="cn.leilei.myssm.domain.Product" >
    <id column="id" property="id"  />
    <result column="product_name" property="productName"  />
    <result column="dir_id" property="dirId" />
    <result column="sale_price" property="salePrice" />
     <!--多对一嵌套结果-->
     <!--productdir的映射,columnPrefix 则为如果在用sql语句给关联对象取了别名情况获取前缀-->
    <association property="productdir" javaType="cn.leilei.myssm.domain.Productdir" columnPrefix="d_">
      <id column="id" property="id"/>
      <result column="dir_name" property="dirName"/>
      <result column="parent_id" property="parentId"/>
    </association>
  </resultMap>

(2)方式二

  <resultMap id="ProductResultMap" type="cn.leilei.myssm.domain.Product" >
    <id column="id" property="id"  />
    <result column="product_name" property="productName"  />
    <result column="dir_id" property="dirId" />
    <result column="sale_price" property="salePrice, property 为当前映射的实体类中关联对象字段中的属性,即查询的属性对应" />
    <!--直接使用result column 为列名 as别名后则用别名 -->
    <result column="d_dir_name" property="productdir.dirName"/>
    <result column="d_parent_id" property="productdir.parentId"/>
   </resultMap>
(3)嵌套查询 关联对象查询的方式之二

嵌套查询则是在sql中不使用join进行关联查询,而是在每个表中分开进行查询 在自己的手动映射中根据关联对象的命名空间+sqlId 确定唯一的sql语句进行关联 ,合并后 展示结果

例如 product 与productdir为多对一关系

多对一嵌套查询sql

  <!--多对一嵌套查询-->
  <select id="selectAll2" resultMap="ProductResultMap">
    SELECT
    p.id,p.product_name,p.dir_id,p.sale_price
    FROM product p
  </select>

在手动映射配置中配置关联对象sql语句 用命名空间+sqlid 进行查找区分 关联为一方,使用association 使用javatype,column 则为当前表与关联表之间的关联桥接(外键) select 为命名空间+sqlid

  <!--配置手动映射-->
  <resultMap id="ProductResultMap" type="cn.leilei.myssm.domain.Product" >
    <id column="id" property="id"  />
    <result column="product_name" property="productName"  />
    <result column="dir_id" property="dirId" />
    <result column="sale_price" property="salePrice" />
    <!--多對一嵌套查詢-->
    <association property="productdir" javaType="cn.leilei.myssm.domain.Productdir" column="dir_id"
                 select="cn.leilei.myssm.mapper.ProductdirMapper.findAll"/>
  </resultMap>

多对一嵌套查询一方额外sql (productdir查询)

    <!--多對一嵌套查询额外sql-->
    <select id="findAll" resultMap="ProductdirResultMap">
        SELECT * from productdir WHERE id=#{dirId};

    </select>
(4)分页插件使用
由于依赖中引入了mybatis的分页插件,则可以直接使用,底层会自动帮们分页  输入当前页和页面长度即可
PageHelper.startPage(pageNum 1, pageSize 4);

Service服务层

公共父服务
public interface IBaseService<T> {
    //根据id查询一个
    T findOneById(Long id);
    //修改
    void update(T t);
    //新增
    void add(T t);
    //高级分页查询
    PageResult<T> findAll(BaseQuery query);
}

具体子服务

public interface IUserService extends IService<User> {

}

实现类 公共父服务实现类

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class IBaseServiceImpl<T> implements IBaseService<T> {
    @Autowired
    private BaseMapper<T> baseMapper;
    @Override
    public T findOneById(Long id) {
        return baseMapper.findOneById(id);
    }

    @Override
    @Transactional
    public void update(T t) {
        baseMapper.update(t);
    }

    @Override
    @Transactional
    public void add(T t) {
        baseMapper.add(t);
    }

    @Override
    @Transactional
    public PageResult<T> findAll(BaseQuery query) {
        PageHelper.startPage(query.getPage(), query.getRows());
        Page<T> page = (Page) baseMapper.findAll(query);//将查出来的结果转换为分页对象
        //从mYbatis分页插件中对象获取数据构成一个新的类(适合于easyui)
        return new PageResult<T>(page);
    }

}

子服务实现

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class IProductServiceimpl extends IBaseServiceImpl<Product> implements IProductService {

    @Autowired
    private ProductMapper productMapper;


    @Override
    @Transactional
    public void updateZT(Long id) {
        Product product1 = productMapper.findOneById(id);
        if (product1.getDirId().equals(Product.OPen)) {//r如果产品对象为开启状态
            product1.setDirId(Product.Close);
            productMapper.update(product1);
        }else if(product1.getDirId().equals(Product.Close)){
            product1.setDirId(Product.OPen);
            productMapper.update(product1);
        }

    }
}

五.简单controller

(1)工具类

1.1AJaxResult 根据ajax请求返回 Ajax结果
package cn.leilei.myssm.util;

public class AjaxResult {
    private boolean success = true;
    private String msg;

    //返回成功的AjaxResult
    public static AjaxResult success(){
        return new AjaxResult();
    }
    //返回有异常的AjaxResult
    public static AjaxResult error(String msg){
        AjaxResult ajaxResult = success();
        ajaxResult.setSuccess(false);
        ajaxResult.setMsg(msg);
        return ajaxResult;
    }

    public boolean isSuccess() {
        return success;
    }

    private void setSuccess(boolean success) {
        this.success = success;
    }

    public String getMsg() {
        return msg;
    }

    private void setMsg(String msg) {
        this.msg = msg;
    }
}

1.2 自定义分页 由于很多前台框架需要传的值是total,rows 所以根据Mybatis分页封装为此分页对象返回前台

实现类中将mybatiszi自带分页对象转为自己的pageresult

    @Override
    public PageResult<T> findAll(BaseQuery query) {
        PageHelper.startPage(query.getPage(), query.getRows());
        Page<T> page = (Page) baseMapper.findAll(query);//将查出来的结果转换为分页对象
        //从mYbatis分页插件中对象获取数据构成一个新的类(适合于easyui,vue等等)
        return new PageResult<T>(page);
    }

PageResult分页对象

package cn.leilei.myssm.util;

import com.github.pagehelper.Page;

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


//分頁對象 用于存储总条数以及每页数据  (Mybatis分页插件有数据  但是格式不满足easyui  所以进行此设置
public class PageResult<T> {

    private long total = 0;

    private List<T> rows = new ArrayList();

    public PageResult() {
    }
    public PageResult(Page<T> page) {
        this.total = page.getTotal();
        this.rows = page.getResult();
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }

}

package cn.leilei.myssm.web.controller;

import cn.leilei.myssm.domain.Product;
import cn.leilei.myssm.query.BaseQuery;
import cn.leilei.myssm.query.ProductQuery;
import cn.leilei.myssm.service.IProductService;
import cn.leilei.myssm.util.AjaxResult;
import cn.leilei.myssm.util.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private IProductService productService;

    @RequestMapping("/index")
    public String index() {
        return "product/employee";
    }

    //查询所有 高級查詢
    @RequestMapping("/findAll")
    @ResponseBody
    public PageResult index(ProductQuery query) {
        return productService.findAll(query);
    }
    //新增或者修改产品
    @RequestMapping("/save")
    @ResponseBody
    public AjaxResult add(Product product) {
        try {
            if (product.getId()!=null){
                productService.update(product);
            }else{
                productService.add(product);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("葫芦小金刚在此:出错啦");
        }
    }
    //修改状态
    @RequestMapping("/zt")
    @ResponseBody
    public AjaxResult zt(Long id) {
        try {
            productService.updateZT(id);
            return AjaxResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("葫芦小金刚在此:出错啦");
        }
    }
}

六.小小测试

    /*高级查询的测试  mybatis的自带分页*/
    @Test
    public void testfindALlByquery() {
        MyQuery myQuery = new MyQuery();
        myQuery.setProductName("罗技");
/*        myQuery.setMaxsalePrice(300D);
        myQuery.setMinsalePrice(200D);*/
        PageHelper.startPage(1, 4);
        productSerivce.findAllByquery(myQuery).forEach(e -> System.out.println(e));
    }
    
   --------控制台信息------
   Product{id=10, productName='罗技M50', dirId=1, salePrice=135.0}
   Product{id=11, productName='罗技M505', dirId=0, salePrice=148.0}
   Product{id=12, productName='罗技M555', dirId=1, salePrice=275.0}
   Product{id=13, productName='罗技M905', dirId=1, salePrice=458.0}
    //刪除多條數據測試
    @Test
    public void testmoreDelete() {
        List<Long> ids = Arrays.asList(4L, 5L, 6L);
        productSerivce.moreDelete(ids);
    }

    //修改
    @Test
    public void testupdate() {
        Product product = new Product();
        product.setId(7L);
        product.setProductName("clearlove7");
        productSerivce.update(product);
    }

    //批量新增测试
    @Test
    public void testmoreAdd() {
        List<Product> productList = Arrays.asList(new Product("a", 1L, 2D),
                new Product("b", 2L, 3D));
        productSerivce.moreAdd(productList);
    }

    //多對一嵌套結果測試
    @Test
    public void testselectAll() {
        productSerivce.selectAll().forEach(e -> System.out.println(e));
    }
发布了31 篇原创文章 · 获赞 23 · 访问量 3811

猜你喜欢

转载自blog.csdn.net/leilei1366615/article/details/98995567