• SSM整合(2): spring 与 mybatis 整合


    在进行完spring与springmvc整合之后, 继续 spring与mybatis的整合.

    既然是操作数据库, 那必然不能缺少了连接属性

    一. db.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=root

    二. application.xml

    将前一篇注释的部分, 再注释回来就行了, 是一个import操作

    三. spring和mybatis的整合xml文件: spring-mybatis.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:p="http://www.springframework.org/schema/p"
           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-3.1.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.1.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">
    
        <!-- 自动搜索bean -->
        <!-- <context:annotation-config/>-->
    
        <!-- 自动扫描 -->
        <!--<context:component-scan base-package="org.elvin.ssm" />-->
    
        <!-- 引入配置文件 -->
        <context:property-placeholder location="classpath:conf/db.properties" />
    
        <!--配置数据库连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <!--driverClassName会自动识别, 可以不配置-->
            <property name="driverClassName" value="${jdbc.driver}" />
    
            <!-- 配置初始化大小、最小、最大 -->
            <!--
                initialSize:初始化时建立物理连接的个数, 默认为0
                minIdle:最小连接池数量
                maxActive:最大连接池数量, 默认为8
            -->
            <property name="initialSize" value="1" />
            <property name="minIdle" value="1" />
            <property name="maxActive" value="20" />
    
            <!--获取连接时最大等待时间,单位ms-->
            <property name="maxWait" value="60000" />
    
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="60000" />
    
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="300000" />
    
            <!--
                validationQuery:用来检测连接是否有效的sql
                testWhileIdle:建议配置为true,默认false, 不影响性能,并且保证安全性,申请连接的时候检测,如果空闲时间大于
                              timeBetweenEvictionRunsMillis, 执行validationQuery检测连接是否有效。
                testOnBorrow:申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。默认true
                testOnReturn:归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
            -->
            <property name="validationQuery" value="SELECT 1 " />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
    
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
            <!--<property name="poolPreparedStatements" value="true" />
            <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />-->
    
            <!-- 监控统计用的filter:stat
            日志用的filter:log4j
            防御sql注入的filter:wall -->
            <!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
            <property name="filters" value="stat" />
        </bean>
    
        <!-- mybatis 的工厂 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="configLocation" value="classpath:conf/mybatis.xml"/>
            <!-- 自动扫描mapping.xml文件 -->
            <property name="mapperLocations" value="classpath:mapper/**/*.xml" />
        </bean>
    
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="org.elvin.ssm.mapper" />
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        </bean>
    
        <!-- 配置事务管理器 -->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <!-- 注解方式配置事物 -->
        <!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->
    
        <!-- 拦截器方式配置事物 -->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="get*" isolation="REPEATABLE_READ" read-only="true" />
                <tx:method name="find*" isolation="REPEATABLE_READ" read-only="true" />
                <tx:method name="search*" isolation="REPEATABLE_READ" read-only="true" />
                <tx:method name="load*" isolation="REPEATABLE_READ" read-only="true" />
    
                <tx:method name="*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
            </tx:attributes>
        </tx:advice>
        
        <aop:config>
            <aop:pointcut id="pointCut" expression="execution(* org.elvin.ssm.service..*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut" />
        </aop:config>
    </beans>

    四. mybatis本身也可以有一个对自己的配置文件. mybatis.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>
        <typeAliases>
            <package name="org.elvin.ssm.pojo" />
        </typeAliases>
    </configuration>

    如果没有什么特别的配置, 这里也可以不写, 这个文件也可以不要, 但是要在spring-mybatis.xml文件中删除  configLocation 的配置

    五. 加入日志文件 log4j.properties

    log4j.rootLogger=DEBUG,Console,FILE  
    #Console
    log4j.appender.Console=org.apache.log4j.ConsoleAppender  
    log4j.appender.Console.layout=org.apache.log4j.PatternLayout  
    log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n  
    #File Appender
    log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender  
    log4j.appender.FILE.File=C:/soft/logs/SSM.log  
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout  
    log4j.appender.FILE.layout.ConversionPattern=[%d{HH:mm:ss,SSS}] [%l] [%t] [%-5p] : %m%n  
    
    log4j.logger.java.sql.ResultSet=INFO  
    log4j.logger.org.apache=INFO  
    log4j.logger.java.sql.Connection=INFO  
    log4j.logger.java.sql.Statement=INFO  
    log4j.logger.java.sql.PreparedStatement=INFO

    然后需要在web.xml文件中加入配置

        <!-- 加载log4j的配置文件log4j.properties -->
        <context-param>
            <param-name>log4jConfigLocation</param-name>
            <param-value>
                classpath:conf/log4j.properties
            </param-value>
        </context-param>
        <!-- 设定刷新日志配置文件的时间间隔,这里设置为10s -->
        <context-param>
            <param-name>log4jRefreshInterval</param-name>
            <param-value>10000</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
        </listener>

    六. 后台代码

    在mapper文件夹下, 加入一个mapper文件. BookMapper.java

    package org.elvin.ssm.mapper;
    
    import org.elvin.ssm.pojo.Book;
    
    import java.util.List;
    
    /**
     * author: Elvin
     * datetime: 2017/12/2 8:21
     * description:
     */
    public interface BookMapper {
    
        /**
         * 根据id查询实体数据
         * @param id
         * @return
         */
        public Book find(Integer id);
    
        /**
         * 获取数据库中所有的数据
         * @return
         */
        public List<Book> getAll();
    
        /**
         * 新增
         * @param book
         * @return
         */
        public Integer insert(Book book);
    
        /**
         * 修改
         * @param book
         */
        public void update(Book book);
    
        /**
         * 删除
         * @param id
         */
        public void remove(Integer id);
    }

    这个文件是一个接口文件, 这里不需要我们手动去实现这个接口, 只需要在resources/mapper文件夹下, 加入对应的xml文件就可以了

    <?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="org.elvin.ssm.mapper.BookMapper">
    
        <select id="find" parameterType="java.lang.Integer" resultType="org.elvin.ssm.pojo.Book">
          select * from book where id=#{id}
        </select>
    
        <select id="getAll" resultType="org.elvin.ssm.pojo.Book">
            select * from book
        </select>
    
        <insert id="insert" parameterType="org.elvin.ssm.pojo.Book" >
            insert into book(name, price, publishTime) values(#{name}, #{price}, #{publishTime})
        </insert>
    
        <update id="update" parameterType="org.elvin.ssm.pojo.Book">
            update book set name=#{name}, price=#{price}, publishTime=#{publishTime} where id=#{id]}
        </update>
    
        <delete id="remove" parameterType="java.lang.Integer">
            delete from book where id=#{id}
        </delete>
    
    </mapper>

    这样, dao中的部分, 就完成了. 接下来, 完成service中的部分

    package org.elvin.ssm.service;
    
    import org.elvin.ssm.pojo.Book;
    
    import java.util.List;
    
    public interface BookService {
        /**
         * 根据id查询实体数据
         * @param id
         * @return
         */
        public Book find(Integer id);
    
        /**
         * 获取数据库中所有的数据
         * @return
         */
        public List<Book> getAll();
    
        /**
         * 新增
         * @param book
         * @return
         */
        public Integer insert(Book book);
    
        /**
         * 修改
         * @param book
         */
        public void update(Book book);
    
        /**
         * 删除
         * @param id
         */
        public void remove(Integer id);
    }

    其实现类:

    package org.elvin.ssm.serviceimpl;
    
    import com.alibaba.druid.support.logging.Log;
    import com.alibaba.druid.support.logging.LogFactory;
    import com.alibaba.fastjson.JSON;
    import org.elvin.ssm.mapper.BookMapper;
    import org.elvin.ssm.pojo.Book;
    import org.elvin.ssm.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    /**
     * author: Elvin
     * datetime: 2017/12/2 8:26
     * description:
     */
    @Service("bookService")
    public class BookServiceImpl implements BookService {
    
        Log logger = LogFactory.getLog(BookServiceImpl.class);
    
        @Autowired
        private BookMapper bookMapper;
    
        /**
         * 根据id查询实体数据
         * @param id
         * @return
         */
        public Book find(Integer id){
            logger.info("find book : " + id);
            return bookMapper.find(id);
        }
    
        /**
         * 获取数据库中所有的数据
         * @return
         */
        public List<Book> getAll(){
            logger.info("getAll book");
            return bookMapper.getAll();
        }
    
        /**
         * 新增
         * @param book
         * @return
         */
        public Integer insert(Book book){
            logger.info("insert book : " + JSON.toJSONString(book));
            return bookMapper.insert(book);
        }
    
        /**
         * 修改
         * @param book
         */
        public void update(Book book){
            logger.info("update book : " + JSON.toJSONString(book));
            bookMapper.update(book);
        }
    
        /**
         * 删除
         * @param id
         */
        public void remove(Integer id){
            logger.info("remove book : " + id);
            bookMapper.remove(id);
        }
    }

    controller中, 新建一个控制器, 来验证一下程序是否能正常运行

    package org.elvin.ssm.controller;
    
    import org.elvin.ssm.pojo.Book;
    import org.elvin.ssm.pojo.ResModel;
    import org.elvin.ssm.service.BookService;
    import org.joda.time.DateTime;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.*;
    
    /**
     * author: Elvin
     * datetime: 2017/11/29 20:06
     * description:
     */
    @Controller
    @RequestMapping("hello")
    public class HelloController {
    
        @Autowired
        private BookService bookService;
    
        @RequestMapping("index")
        public String index(ModelMap model){
    
            List<Book> bookList = bookService.getAll();
    
            model.put("bookList", bookList);
    
            return "index";
        }
    
        @RequestMapping(value = "book/{id}", method = {RequestMethod.GET, RequestMethod.POST})
        @ResponseBody
        public Book book(@PathVariable("id") Integer id){
           Book b = bookService.find(id);
           return b;
        }
    
        @RequestMapping(value = "get", method = RequestMethod.POST)
        public @ResponseBody Map<String, Object> getData(@RequestParam("id") Integer id){
            Map<String, Object> map = new HashMap<>();
            map.put("name", "hahhha");
            map.put("age", 20);
            return map;
        }
    
        @GetMapping("addData")
        @ResponseBody
        public ResModel addData(){
            ResModel resObj = new ResModel("新增数据失败", 0, null);
            try{
                List<Book> list = getBookList();
                list.forEach(n->{
                    bookService.insert(n);
                });
                resObj.setMsg("新增成功");
                resObj.setCode(1);
            }
            catch (Exception e){
                System.out.println(e.getMessage());
    
            }
            return resObj;
        }
    
        //region private method
        private List<Book> getBookList(){
            List<Book> bookList = new ArrayList<>();
            String[] nameStrs = {"吴", "一", "雪", "动", "额", "阿", "前", "里", "排"};
            Random r = new Random();
            String timeStr = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
            for (int i = 0; i < 10 ; i++){
                Book b = new Book();
                b.setId(i+1);
                b.setName(nameStrs[r.nextInt(5)] + nameStrs[r.nextInt(9)]);
                b.setPublishTime(timeStr);
                b.setPrice(r.nextInt(100));
                bookList.add(b);
            }
            return bookList;
        }
        //endregion
    }

    这里我做了一个Json数据返回的规范实体

    package org.elvin.ssm.pojo;
    
    /**
     * author: Elvin
     * datetime: 2017/12/2 13:19
     * description:
     */
    public class ResModel {
        private String msg;
    
        private Integer code;
    
        private Object resObj;
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public Object getResObj() {
            return resObj;
        }
    
        public void setResObj(Object resObj) {
            this.resObj = resObj;
        }
    
        public ResModel(String msg, Integer code, Object resObj) {
            this.msg = msg;
            this.code = code;
            this.resObj = resObj;
        }
    }

    七. 验证

    1. 加数据到数据库中

    这里的价格和时间, 我在数据库中用的是 int 和 varchar 类型的.  在实际使用中, 价格不要使用decimal去存储, 看需求, 如果money不是很大, 可以用int, 如果大, 则使用long来存储. 这样能保证数据的精确性. 而对于时间类型, 使用字符串类型去处理, 其实完全是可以的, 并且在实际使用中, 我觉得更方便. 

    有了数据之后, 可以来查询一下

     

  • 相关阅读:
    P1908 逆序对
    P1967 货车运输
    成也DP,败也DP(AFO?)
    Review Before THUWC2020
    THUWC2020游记
    loj6295. 无意识之外的捉迷藏
    loj6504. 「雅礼集训 2018 Day5」Convex
    某道XJ题
    loj2304. 「NOI2017」泳池
    loj6435. 「PKUSC2018」星际穿越
  • 原文地址:https://www.cnblogs.com/elvinle/p/7954069.html
Copyright © 2020-2023  润新知