1. 程式人生 > >SSM整合(2): spring 與 mybatis 整合

SSM整合(2): spring 與 mybatis 整合

分享 eth point names space json cal 返回 autowired

在進行完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來存儲. 這樣能保證數據的精確性. 而對於時間類型, 使用字符串類型去處理, 其實完全是可以的, 並且在實際使用中, 我覺得更方便.

有了數據之後, 可以來查詢一下

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

SSM整合(2): spring 與 mybatis 整合