文章出處

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

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

 

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()