Fork me on GitHub

Mybatis与Spring和servlet之间的集成

首先:

mybatis原配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    
    <settings>
        <!--开启懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <typeAliases>
        <typeAlias type="com.sxt.pojo.User" alias="user"/>
    </typeAliases>
    <environments default="mybatis">
        <!-- 这里配置的id是上面default指定的默认指定模式 -->
        <environment id="mybatis">
            <!--配置事物:
                1.一般是JDBC ,不能乱写 如果乱写会报一个类找不到异常
                    作用:从数据源来获取连接,管理事物
                2.MANAGED:这个一般什么都不做,它从来不回滚或者提交一个事物
                    它是让容器来管理一个事物的提交或者回滚。
                    默认情况下,MANAGED会自动关闭连接,如果我们需要他不自动关闭,就这么设置
                    <transactionManager type="MANAGED">
                        <property name="closeConnection" value="false"/>
                    </transactionManager>
            -->
            <transactionManager type="JDBC"></transactionManager>
            <!--
                1.UNPOOLED: 这个数据源的实现只是每次被请求时打开和关闭连接

                2.POOLED:   这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,
                            避免了创建新的连接实例时所必需的初始化和认证时间。
                            这是一种使得并发 Web 应用快速响应请求的流行处理方式

                3.JNDI:     这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,
                            容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用
             -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?
                serverTimezone=Asia/Shanghai&amp;useSSL=false&amp;
                rewriteBatchedStatements=true&amp;useOldAliasMetadataBehavior=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/sxt/mapper/UserMapper.xml"/>
        <!--<package name="com.sxt.mapper"/>-->
    </mappers>
</configuration>

mapper配置:

接口:

package com.sxt.dao;

import com.sxt.pojo.User;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @program:
 * @description:
 * @author: Mr.Zhang
 * @create: 2021-09-20 11:00
 **/
@Repository
public interface UserDao {
    //增加学生
    void saveUser(User user);

    //删除学生
    void delUser(Integer id);

    //修改学生信息
    void updateUser(User user);

    //通过id查询学生
    User loadUserById(Integer id);

    //查询所有学生
    List<User> loadUserList();

    //多条件查询
    List<User> loadUserListByParams(User user);
}

 

这里由于已经进行继承,修改了其别名

<?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">
<!--
    namespace:  填写映射当前的Mapper接口,
                所有的增删改查的参数和返回值类型,
                就可以直接填写缩写,不区分大小写直接通过方法名去查找类型
-->
<mapper namespace="com.sxt.dao.UserDao">
    <!--
        1.定义sql片段:用于提取重复的代码
          要使用该代码的时候就可以直接使用<include>标签
          id:为提取的sql代码取一个名,起一个标识作用。
    -->
    <sql id="select">
      select * from t_user
    </sql>

    <!--
        方法:User loadUserById(Integer id);
        id:填写在接口类中的方法名
        parameterType:填写参数的类型
        resultType:填写方法中返回值的类型,不用写完全限定名,不区分大小写
    -->
    <select id="loadUserById"
            parameterType="Integer"
            resultType="com.sxt.pojo.User">

      <include refid="select"/>
      where id = #{id}
    </select>

    <!--
        方法:List<User> loadUserList();
        resultMap属性:与resultMap标签一起使用,填写resultMap的id属性的值
    -->
    <select id="loadUserList" resultMap="users">
      <include refid="select"/>
    </select>

    <!--
        resultMap标签:用于自定义封装结果
            属性:type:最终结果封装到实体类中,type就是指定封装到具体的哪一个实体类
            属性:id  :与select标签中的resultMap属性的值一样,一定要唯一
                子标签:<id>    :该标签指定主键封装到实体类中的哪一个属性
                子标签:<result>:该标签指定其他的列封装到实体类中的那一个属性,一般只
                                    需要填写实体类中的属性,与表中的列不同的列名
                                    让其实体类中的属性与表中的那一列形成映射
    -->
    <resultMap id="users" type="com.sxt.pojo.User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <result property="cid" column="cid"/>
    </resultMap>



    <!--
        方法:List<User> loadUserListByParams(User user);
        运用方式:mybatis的懒加载:链表查询,多条件查询中标签Where的运用
            select u.id,u.name,u.sex,u.birthday,u.cid,c.id clsid,c.cname
            from t_user u left join t_class c on u.cid = c.id
        懒加载:只加载一部分,另一部分调用的时候加载

    -->
    <resultMap id="user_cls" type="com.sxt.pojo.User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <result property="cid" column="cid"/>
        <association property="cls" javaType="com.sxt.pojo.Classes" select="loadClasses" column="cid">
            <id property="id" column="id"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>
    <!--
        主表User表
    -->
    <select id="loadUserListByParams" resultMap="user_cls" parameterType="com.sxt.pojo.User">
      select id,`name`,sex,birthday,cid from t_user  where id = #{id}
    </select>
    <!--
        副表,班级表
    -->
    <select id="loadClasses" resultType="com.sxt.pojo.Classes" parameterType="Integer">
      select c.id ,c.cname from t_class c where c.id =#{cid}
    </select>

    <!--多条件查询
        一般用三种字标签: select标签中有<where>标签,标签作用自动加一个where,自动截取第一个and
                        update标签中有<set>  标签,标签作用自动加一个set  ,自动截取一个逗号
                        全部标签都可以有<trim> 下面示例:updateUser
    -->
    <update id="updateUser" parameterType="com.sxt.pojo.User">
        update t_user
        /*set标签:自动添加一个set*/
        <!--<set>
            /*if标签,和jstl表达式基本上一样,可以进行简单的逻辑判断,比如说判断大小,判断是否为空,三元运算符,长度等*/
            <if test="name!=null and name!=''" >
              `name` = #{name},
            </if>
            <if test="sex!=null and sex!=''" >
              `sex` = #{sex},
            </if>
            <if test="birthday!=null and birthday!=''" >
              `birthday` = #{birthday},
            </if>
            <if test="cid!=null and cid!=''" >
              `cid` = #{cid},
            </if>
        </set>-->
        /*
          新的标签trim运用
          有前缀,前缀截取,后缀,后缀截取
          比如说,这里就是截取最后后缀的逗号
          如果是前缀(prefix),那么就是截取前面的set,其他类似类推
        */
        <trim suffixOverrides=",">
            set
            <if test="name!=null and name!=''" >
                `name` = #{name},
            </if>
            <if test="sex!=null and sex!=''" >
                `sex` = #{sex},
            </if>
            <if test="birthday!=null and birthday!=''" >
                `birthday` = #{birthday},
            </if>
            <if test="cid!=null and cid!=''" >
                `cid` = #{cid},
            </if>
        </trim>
        where id = #{id}
    </update>

</mapper>

 

以上是原有的mybatis配置


 

 然后,整合mybatis与spring

<?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:aop="http://www.springframework.org/schema/aop"
       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
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
        ">
    <!--
        注解方式使用Spring的自动装配
        1.给业务层装配userDao
        2.给Web层装配userService
    -->
    <context:component-scan base-package="com.sxt.service.impl,com.sxt.servlet"/>


    <!--
        spring-mybatis整合
        问题
            1:Spring注解只能给自动的创建层与层之间的关系,那么如何开启数据库连接呢?
    -->

    <!--第一步:
        1.整合数据库连接
            使用德鲁伊:Driuid连接池,不再使用原来的JDBC

        2.作用:
            通过连接池产生一个collection对象

        3.目的:id属性:      给这个connection对象取一个id作为引用
               class属性:   给这个类中的属性赋值

               property属性:
                        name: 是set后面的方法名,为了给特定的属性赋值
                        value:赋予的值
    -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/ssm?
                serverTimezone=Asia/Shanghai&amp;useSSL=false&amp;
                rewriteBatchedStatements=true&amp;useOldAliasMetadataBehavior=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>

    </bean>

    <!--第二步:产生一个对connection对象产生代理的工厂对象
            总之:这个SqlSessionFactoryBean封装了mybatis配置文件的所有属性

            1.目的:产生sqlSessionFactory
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!--引用上面的connection对象给其属性赋值,赋值方法为setDataSource,所以填dataSource-->
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.sxt.pojo"></property>

        <!--引用mybatis文件,但是这里不需要-->
        <!--<property name="configLocation" value="classpath:mybatis-config.xml"/>-->

        <!--引用mapper.xml文件的增删改查
            private Resource[] mapperLocations;
            其值为一个数组,所以用list包裹,然后指定value
        -->
        <property name="mapperLocations" >
            <list>
                <value>classpath:com/sxt/mapper/*.xml</value>
            </list>
        </property>

    </bean>

    <!--第三步产生mapper
            通过sqlSessionFactory产生
            1.通过扫描一个接口的路径产生其对象
            2.通过工厂产生的对象获取sqlSession对象getMapper(接口的class对象),其参数通过扫描com.sxt.dao里面的接口类获取
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.sxt.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>


    <!--配置数据库事务管理

            1.配置事物,由上面的connection对象管理
    -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>


    <!--配置事物切面

        name属性(方法名):       表示以什么开头的方法
        isolation属性(隔离):   表示事物的隔离级别:脏读,幻读等
        propagation属性(传播): 表示事物的传播级别:required表示必须在一个事物中,
                                    如果没有事物那么就开启一个事物,如果有事物就放入一个事物中
        read-only(只读):值:false/true
    -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED"/>
            <tx:method name="del*" isolation="DEFAULT" propagation="REQUIRED"/>
            <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/>
            <tx:method name="load*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>

            <!--如果name为*表示出了上面配置的其他方法-->
            <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!--切面织入配置
            属性aop:pointcut:配置的切入点
            属性aop:advisor :织入
                    advice-ref:  织入的切面
                    pointcut-ref:切入点引用
    -->
    <aop:config>
        <aop:pointcut id="pc" expression="execution(* com.sxt.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
    </aop:config>
</beans>

 

servlet调用

package com.sxt.servlet;

import com.sxt.pojo.User;
import com.sxt.service.UserService;
import com.sxt.utils.BaseServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @program:
 * @description:
 * @author: Mr.Zhang
 * @create: 2021-09-21 23:05
 **/
@WebServlet(name = "userServlet",urlPatterns = "/user")
public class UserServlet extends BaseServlet {

    private UserService userService;
    /**
     * 加载User列表
     * **/
    public void loadUserListServlet(
            HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException {

    }

    /**
     * 添加一个User
     * **/
    public void saveUserServlet(
                HttpServletRequest req,
                    HttpServletResponse resp)
                        throws ServletException, IOException {

    }
    /**
     * 删除一个User
     * **/
    public void delUserServlet(
            HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException {

    }
    /**
     * 更新一个User
     * **/
    public void updateUserServlet(
            HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException {
        /**
         * 因为其有两个容器,我们需要的是tomcat容器调用方法的时候自动加载spring容器
         * 通过WebApplicationContext的监听器自动加载spring的位置
         * 然后,通过application获取Spring容器中的业务层对象
         * */

        String cid = req.getParameter("cid");
        //**************************************************************
        WebApplicationContext context =
            WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());

/*        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");*/
        //**************************************************************

        //其他的基本没什么变化
        userService = (UserService)context.getBean("userServiceImpl");

        User user = new User();
        user.setId(1);
        user.setCid(Integer.parseInt(cid));

        userService.updateUserService(user);
    }
    /**
     * 查找一个User
     * **/
    public void loadUserServlet(
            HttpServletRequest req,
            HttpServletResponse resp)
            throws ServletException, IOException {

    }
}

以上:用**************包含起来的两行都能获取Spring容器,运行没有什么区别,小白起初觉得用监听器来加载Spring容器,完全是画蛇添足,

  后来小白白才知道,用Tomcat启动,其整个Tomcat只会有一个Spring容器。如果是通过加载Spring容器的方式会浪费很多的时间。所以整合servlet与spring容器用context监听器的方式才是正确的。

web配置

<?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_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-config.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

 

如果是要配置分页:

那么需要实现plugins配置如下:

 <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <props>
                            <prop key="helperDialect">mysql</prop>
                            <prop key="reasonable ">true</prop>
                            <prop key="pageSizeZero ">true</prop>
                        </props>
                    </property>
                </bean>
            </array>
        </property>

 

posted @ 2021-09-22 21:17  fat_fox  阅读(149)  评论(0)    收藏  举报