SSM小demo——記賬系統

小王曾是少年發表於2020-10-31

1 前言

  本demo是基於SSM框架完成的一個小專案,用於初學者進行基本的框架熟練度練習。原始碼獲取方式在文末,以下是程式執行的幾個頁面:
在這裡插入圖片描述
在這裡插入圖片描述

2 環境搭建

2.1 基本架構

在這裡插入圖片描述
1. 新增依賴包,可以通過properties統一框架版本

<properties>
    <springversion>5.0.8.RELEASE</springversion>
</properties>
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>

  <!-- 加入ServletAPI -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!-- MySQL依賴 start -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
  </dependency>
  <!-- 加入MyBatis 依賴 start -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
  </dependency>
  <!-- 引入Spring(包含SpringMVC) 依賴 start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${springversion}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${springversion}</version>
  </dependency>
  <!-- 引用外掛依賴:MyBatis整合Spring,如果mybatis版本在3.4及以上版本
  mybatis-spring的版本要在1.3以上 -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.2.2</version>
  </dependency>
  <!-- JSTL -->
  <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <!-- 德魯伊資料連線池 -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.9</version>
  </dependency>
  <!-- pagehelper -->
  <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.6</version>
  </dependency>
  <!--處理json-->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
  </dependency>
  <!--javaee-->
  <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
  </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.4</version>
  </dependency>
</dependencies>

如果遇到宣告式事務報錯,需要新增下面的依賴包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.1</version>
</dependency>

2. 新增spring配置檔案
實現8個關鍵步驟

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--1 配置資料來源-->
    <bean id="db" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/kaikeba0917"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!--2 建立sqlSessionFactory-->
    <bean id="fac" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="db"/>
        <!--指定mybatis的配置檔案路徑-->
        <property name="configLocation" value="classpath:mybatis.xml"/>
        <!--指定mybatis的mapper檔案路徑-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!--3 建立sqlSessionTemplate(這個類沒有無參構造)-->
    <bean class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="fac"/>
    </bean>

    <!--4 配置事務-->
    <bean id="mytx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="db"/>
    </bean>
    <tx:annotation-driven transaction-manager="mytx"/>

    <!--5 啟用springMVC註解-->
    <mvc:annotation-driven/>

    <!--6 配置檢視解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--7 掃描註解包-->
    <context:component-scan base-package="com.wangjiawei"/>

    <!--8 配置靜態資源訪問-->
    <mvc:default-servlet-handler/>

</beans>

3. 配置web.xml檔案,同時載入spring配置檔案

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">


  <display-name>Archetype Created Web Application</display-name>

  <!--1 配置前端控制器-->
  <servlet>
    <servlet-name>aa</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>aa</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--2 處理post亂碼-->
  <filter>
    <filter-name>bb</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>
  </filter>

  <filter-mapping>
    <filter-name>bb</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

4. 建立資料表,新增專案包結構,包括實體類等
  給dao,service,web(controller)包下使用註解建立物件,給service,web中的屬性注入物件
dao:

public interface BooksDao {
    public List<Books> getAll();
}
@Repository
public class BookDaoImpl implements BooksDao {

    /** 該物件來源於配置檔案
     *
     */
    @Resource
    private SqlSessionTemplate sqlSessionTemplate;

    @Override
    public List<Books> getAll() {
        return sqlSessionTemplate.selectList("com.wangjiawei.dao.BooksDao.getAll");
    }
}

service:

public interface BooksService {
    public List<Books> getAll();
}
@Service
public class BooksServiceImpl implements BooksService {
    @Resource
    private BooksDao dao;

    @Override
    public List<Books> getAll() {
        return dao.getAll();
    }
}

web(controller):

@Controller
public class BooksController {
    @Resource
    private BooksService booksService;

    @RequestMapping("/getallbooks")
    public String getAll(ModelMap map){
        List<Books> books = booksService.getAll();
        map.addAttribute("booklist", books);
        return "show";
    }
}

5. 配置檔案程式碼mybatis.xml 及相應的 BooksMapper.xml
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>
<!--        <typeAlias type="com.wangjiawei.bean.Student" alias="stu"></typeAlias>-->
        <package name="com.wangjiawei.bean"/>
    </typeAliases>

    <!--分頁外掛-->
    <plugins>
        <!-- PageHelper4.1.6 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>

</configuration>

BooksMapper.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="com.wangjiawei.dao.BooksDao">
    <select id="getAll" resultType="books">
        select * from books
    </select>
</mapper>

6. 配置controller檔案
使用的註解:
@Controller
@RequestMapping
@AutoWired
@Qualifier(“empBiz”)
(同上面的步驟4)

7. 新增service,dao層
使用的註解:
@Service
@AutoWired
(1) dao層省略了實現類
(2) dao 層只定義介面,由小樹葉建立dao層物件以及掃描mapper檔案
注:當新增了spring-jdbc的jar包後,會自動提交事務

8. 前端測試網頁
index.jsp:

<html>
<body>
<h2>Hello World!</h2>
<a href="/getallbooks">getallbooks</a>
</body>
</html>

show.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>show.jsp</h1>
    <c:forEach items="${booklist}" var="book">
        ${book.bookId}——${book.bookName}
    </c:forEach>
</body>
</html>

關於其中的配置檔案:
  當專案啟動時載入web.xml檔案,web.xml檔案載入spring.xml檔案,spring的配置檔案又去載入了mybatis的配置檔案與mapper檔案。

2.2 省略dao實現類

先將上面的dao實現類刪掉

在這裡插入圖片描述
使用MapperScannerConfigurer替代SqlSessionTemplate

<!--省略實現類-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.dao"></property>
    <property name="sqlSessionFactoryBeanName" value="fac"></property>
</bean>

注意:此時也可以測試使用屬性檔案的方式來載入資料來源(支援屬性檔案連結資料來源)
在這裡插入圖片描述

2.3 ssm整合mybatis反向生成工具

依賴包:

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.5</version>
</dependency>

載入外掛:

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
                <!--配置檔案的路徑-->
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                <overwrite>true</overwrite>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.5</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

根據外掛中的內容,在resource資料夾下建立generatorConfig.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>
    <!--資料庫驅動jar -->
    <classPathEntry
            location="F:\develop\maven_repository\mysql\mysql-connector-java\5.1.6\mysql-connector-java-5.1.6.jar" />
    <context id="MyBatis" targetRuntime="MyBatis3">
        <!--去除註釋 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--資料庫連線 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/kaikeba0917"
                        userId="root"
                        password="root">
        </jdbcConnection>
        <!--生成實體類 指定包名 以及生成的地址 (可以自定義地址,但是路徑不存在不會自動建立
        使用Maven生成在target目錄下,會自動建立) -->
        <javaModelGenerator targetPackage="com.wangjiawei.bean"
                            targetProject="D:\程式設計師\開課吧新職課\11SSM\5SSM整合\ssm\src\main\java">
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!--生成SQLmapper檔案 -->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="D:\程式設計師\開課吧新職課\11SSM\5SSM整合\ssm\src\main\resources">
        </sqlMapGenerator>
        <!--生成Dao檔案,生成介面 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.wangjiawei.dao"
                             targetProject="D:\程式設計師\開課吧新職課\11SSM\5SSM整合\ssm\src\main\java">
        </javaClientGenerator>
        <table tableName="student" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false"
               enableSelectByExample="false" selectByExampleQueryId="false">
        </table>
    </context>
</generatorConfiguration>

maven型別的web專案載入mybatis-generator外掛:

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
注意:反向生成後,最好把該指令刪除,否則不小心點了之後,又會生成一遍程式碼,尤其是mapper.xml檔案中sql語句又會生成一遍,執行時會報錯。

3 記賬專案

3.1 需求分析

3.1.1 記賬管理

在這裡插入圖片描述
其中,查詢條件中型別為下拉選單,可選值有“不限,支出,收入,轉賬,借出,借入,還入,還出”。日期輸入框需要輸入“yyyy-MM-dd”格式的日期字串,點選“搜尋”按鈕提交表單,提交時如果輸入項不符合輸入要求,則顯示相應提示資訊。列表中根據記賬類別在金額前新增相應的“+,-”符號,如果類別為“支出,借出,還出”時在金額前新增“-”。
如果類別為“收入,借入,還入”時在金額前新增“+”。如果根據輸入項進行查詢後沒有找到賬單資料,則給出提示資訊,如圖所示:

在這裡插入圖片描述
點選“記賬”按鈕後,進入記賬頁面。

3.1.2 記賬

在這裡插入圖片描述

  • 型別屬性是單選框, 標題輸入框最長輸入不能超過25 字元, 日期輸入框需要輸入“yyyy-MM-dd”格式的日期字串,金額輸入框必須為大於0 的數,說明輸入框中最大輸入長度為250 字元。
  • 點選“重置”按鈕則恢復初始值
  • 點選“儲存”按鈕執行儲存功能。提交資料至Controller 前必須使用JS 驗證。如果各屬性輸入值不符合要求則需提示使用者。
  • 點選“返回”按鈕放棄當前記賬操作。並返回首頁。

功能補充:在“說明”列後加一列,叫“操作”。使用者可以刪除或修改資料。
分頁顯示:上一頁 下一頁 首頁 尾頁 當前頁碼 總頁數 總條數

3.1.3 參考資料庫

在這裡插入圖片描述
在這裡插入圖片描述

create table bills(
	id int primary key auto_increment,
	title varchar(50),
	billtime date,
	typeid int,
	price double,
	explains varchar(50)
);

create table billtype(
	id int primary key auto_increment,
	bname varchar(5)
);

3.2 環境搭建

先建立基本的目錄

在這裡插入圖片描述
然後按照上面的步驟配置pom.xml、spring.xml、mybatis.xml、generatorConfig.xml,接著使用mybatis的自動生成功能自動生成

3.3 查詢資料

配置web.xml中的請求分發器,以及處理post亂碼

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>Archetype Created Web Application</display-name>

  <!--1 配置前端控制器-->
  <servlet>
    <servlet-name>aa</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>aa</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--2 處理post亂碼-->
  <filter>
    <filter-name>bb</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>
  </filter>

  <filter-mapping>
    <filter-name>bb</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


</web-app>

3.3.1 展示下拉選單和基本資訊

在這裡插入圖片描述
dao:
BillsMapper

package com.wangjiawei.dao;

import com.wangjiawei.bean.Bills;

import java.util.List;

public interface BillsMapper {

    /**
     * 查詢所有賬單
     * @return
     */
    public List<Bills> getBills();

    int deleteByPrimaryKey(Integer id);

    int insert(Bills record);

    int insertSelective(Bills record);

    Bills selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Bills record);

    int updateByPrimaryKey(Bills record);
}

在BillsMapper.xml中新增對應實現:

<resultMap id="BaseResultMap" type="com.wangjiawei.bean.Bills">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="title" jdbcType="VARCHAR" property="title" />
  <result column="billtime" jdbcType="DATE" property="billtime" />
  <result column="typeid" jdbcType="INTEGER" property="typeid" />
  <result column="price" jdbcType="DOUBLE" property="price" />
  <result column="explains" jdbcType="VARCHAR" property="explains" />
</resultMap>

<select id="getBills" resultMap="BaseResultMap">
  select * from bills
</select>

BillTypeMapper

package com.wangjiawei.dao;

import com.wangjiawei.bean.Billtype;

import java.util.List;

public interface BilltypeMapper {

    /**
     * 查詢所有賬單型別
     * @return
     */
    public List<Billtype> getTypes();

    int deleteByPrimaryKey(Integer id);

    int insert(Billtype record);

    int insertSelective(Billtype record);

    Billtype selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Billtype record);

    int updateByPrimaryKey(Billtype record);
}

在BillTypeMapper.xml中新增對應實現:

<resultMap id="BaseResultMap" type="com.wangjiawei.bean.Billtype">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="bname" jdbcType="VARCHAR" property="bname" />
</resultMap>

<select id="getTypes" resultMap="BaseResultMap">
  select * from billtype
</select>

service層:
BillsService介面:

public interface BillsService {

    /**
     * 查詢所有賬單
     * @return
     */
    public List<Bills> getBills();
}

BillsServiceImpl實現類:

@Service
public class BillsServiceImpl implements BillsService {

    @Resource
    private BillsMapper billsMapper;

    /**
     * 查詢所有賬單
     *
     * @return
     */
    @Override
    public List<Bills> getBills() {
        return billsMapper.getBills();
    }
}

BillTypesService介面:

public interface BillTypesService {

    /**
     * 查詢所有賬單型別
     * @return
     */
    public List<Billtype> getTypes();
}

BillTypesService實現類:

@Service
public class BillTypesServiceImpl implements BillTypesService {
    @Resource
    private BilltypeMapper billtypeMapper;

    /**
     * 查詢所有賬單型別
     *
     * @return
     */
    @Override
    public List<Billtype> getTypes() {
        return billtypeMapper.getTypes();
    }
}

controller層:
BillsController

@Controller
public class BillsController {
    @Resource
    private BillTypesService typesService;
    @Resource
    private BillsService billsService;

    @RequestMapping("/gettypes")
    public String gettypes(ModelMap map){
        // 1 查詢所有賬單型別
        List<Billtype> types = typesService.getTypes();
        // 2 查詢所有的賬單
        List<Bills> bills = billsService.getBills();
        // 儲存資料給前臺
        map.addAttribute("types", types);
        map.addAttribute("bills", bills);
        return "show";
    }
}

相應的前端介面:
index.jsp

<html>
<body>
<script type="application/javascript">
    location.href = "/gettypes";
</script>
</body>
</html>

show.jsp

<%--
  Created by IntelliJ IDEA.
  User: 12291
  Date: 2020/10/30
  Time: 10:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>記賬管理</h1>

<p>
    <form>
    型別:
    <select>
        <option value="-1">不限</option>
        <c:forEach items="${types}" var="tp">
            <option value="${tp.id}">${tp.bname}</option>
        </c:forEach>
    </select>

    時間:
        從<input type="text" name="begin"><input type="text" name="end">
        <input type="submit" value="搜尋">
    </form>
        <input type="button" value="記賬">
</p>
<table border="1" width="500">
    <tr>
        <td>標題</td>
        <td>記賬時間</td>
        <td>類別</td>
        <td>金額</td>
        <td>說明</td>
        <td>操作</td>
    </tr>

    <c:forEach items="${bills}" var="bill">
        <tr>
            <td>${bill.title}</td>
            <td><fmt:formatDate value="${bill.billtime}" pattern="yyyy-MM-dd"/></td>
            <td>類別</td>
            <td>${bill.price}</td>
            <td>${bill.explains}</td>
            <td>刪除 修改</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

3.3.2 前端頁面【類別】部分的顯示

這裡需要兩表聯查:

select * from bills b, billtype t where b.typeid = t.id;

在這裡插入圖片描述
先新增實體類的一對多關係:
Bills類中新增屬性

private Billtype billtype;

BillType中新增屬性

private List<Bills> billsList;

相應的要修改mapper.xml:
BillsMapper.xml(要展示類別只用修改這一個就行了)

<resultMap id="rs1" type="bills">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="title" jdbcType="VARCHAR" property="title" />
  <result column="billtime" jdbcType="DATE" property="billtime" />
  <result column="typeid" jdbcType="INTEGER" property="typeid" />
  <result column="price" jdbcType="DOUBLE" property="price" />
  <result column="explains" jdbcType="VARCHAR" property="explains" />

  <association property="billtype" javaType="com.wangjiawei.bean.Billtype">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="bname" jdbcType="VARCHAR" property="bname" />
  </association>
</resultMap>

<select id="getBills" resultMap="rs1">
  select * from bills b, billtype t where b.typeid = t.id;
</select>

修改前端show.jsp:
在這裡插入圖片描述
在這裡插入圖片描述

3.3.3 前端頁面【金額】部分的顯示

支出,借出時金額應該有一個負號
只用在前端介面中使用choose when即可

<c:forEach items="${bills}" var="bill">
    <tr>
        <td>${bill.title}</td>
        <td><fmt:formatDate value="${bill.billtime}" pattern="yyyy-MM-dd"/></td>
        <td>${bill.billtype.bname}</td>
        <td>
            <c:choose>
                <c:when test="${bill.billtype.bname =='支出' || bill.billtype.bname =='借出' || bill.billtype.bname =='還出'}">
                    -${bill.price}
                </c:when>
                <c:when test="${bill.billtype.bname =='收入' || bill.billtype.bname =='借入' || bill.billtype.bname =='還入'}">
                    +${bill.price}
                </c:when>
                <c:otherwise>
                    ${bill.price}
                </c:otherwise>
            </c:choose>
        </td>
        <td>${bill.explains}</td>
        <td>刪除 修改</td>
    </tr>
</c:forEach>

在這裡插入圖片描述

3.3.4 通過時間和型別模糊查詢

實際上,查詢所有的語句和模糊查詢的語句是同一種語句,只不過模糊查詢的語句是在查詢所有語句的基礎上進行一些拼接,這兩種查詢可以呼叫同一個介面。

前端頁面:
為搜尋這一部分新增一個form

<form action="/getAllBills" method="post">
型別:
<select name="typeid">
    <option value="-1">不限</option>
    <c:forEach items="${types}" var="tp">
        <option value="${tp.id}" ${tid==tp.id?'selected':''}>${tp.bname}</option>
    </c:forEach>
</select>

時間:
    從<input type="text" name="begin" value="${begintime}"><input type="text" name="end" value="${endtime}">
    <input type="submit" value="搜尋">
</form>
    <input type="button" value="記賬">

controller層:
新增查詢所有的方法 getAllBills。
其中新增了回顯操作,由於回顯操作也要根據type的id進行匹配展示(見前端介面),所以這裡也要查詢一下所有的type。

/**
 * 查詢所有賬單
 * @return
 */
@RequestMapping("/getAllBills")
public String getBills(Integer typeid, String begin, String end, ModelMap map){

    List<Bills> bills = billsService.getBills(typeid, begin, end);
    map.addAttribute("bills", bills);
    // 資料回顯
    // 將模糊查詢的條件值再返回給前臺
    map.addAttribute("tid", typeid);
    map.addAttribute("begintime", begin);
    map.addAttribute("endtime", end);

    List<Billtype> types = typesService.getTypes();
    map.addAttribute("types", types);

    return "show";
}

service層:
dao介面:

public List<Bills> getBills(int typeid, String begin, String end);

dao實現類:

/**
 * 查詢所有賬單
 *
 * @return
 */
@Override
public List<Bills> getBills(int typeid, String begin, String end) {
    Map params = new HashMap();
    params.put("tid", typeid);
    params.put("begin", begin);
    params.put("end", end);
    return billsMapper.getBills(params);
}

dao:
修改BillsMapper的getBills方法

public List<Bills> getBills(Map map);

相應的配置檔案BillsMapper.xml

<resultMap id="rs1" type="bills">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="title" jdbcType="VARCHAR" property="title" />
  <result column="billtime" jdbcType="DATE" property="billtime" />
  <result column="typeid" jdbcType="INTEGER" property="typeid" />
  <result column="price" jdbcType="DOUBLE" property="price" />
  <result column="explains" jdbcType="VARCHAR" property="explains" />

  <association property="billtype" javaType="com.wangjiawei.bean.Billtype">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="bname" jdbcType="VARCHAR" property="bname" />
  </association>
</resultMap>

<select id="getBills" resultMap="rs1">
  select * from bills b, billtype t where b.typeid = t.id
  <if test="tid != -1">
    and t.id=#{tid}
  </if>
  <if test="begin!=null and begin!=''">
    and b.billtime>=#{begin}
  </if>
  <if test="end!=null and end!=''">
    and b.billtime <![CDATA[ <= ]]> #{end}
  </if>
</select>

3.3.5 分頁展示

使用工具類PageHelper進行分頁操作,在service層進行這個操作。

service:
分頁查詢需要接收新的引數,當前頁數:index和每頁顯示條數size
介面

public PageInfo<Bills> getBills(int typeid, String begin, String end, int index, int size);

實現類:

@Service
public class BillsServiceImpl implements BillsService {

    @Resource
    private BillsMapper billsMapper;

    /**
     * 查詢所有賬單
     *
     * @return
     */
    @Override
    public PageInfo<Bills> getBills(int typeid, String begin, String end, int index, int size) {
        Map params = new HashMap();
        params.put("tid", typeid);
        params.put("begin", begin);
        params.put("end", end);

        // 1 指定分頁資料
        PageHelper.startPage(index, size);
        // 2 查詢資料
        List<Bills> bills = billsMapper.getBills(params);
        // 3 建立分頁工具類
        PageInfo<Bills> info = new PageInfo<>(bills);

        return info;
    }
}

controller層:
controller中修改查詢操作的呼叫,傳入一個size和index,並且返回給前端的資料變成PageInfo物件

@RequestMapping("/gettypes")
public String gettypes(ModelMap map){
    // 1 查詢所有賬單型別
    List<Billtype> types = typesService.getTypes();

    // 2 查詢所有的賬單
    PageInfo<Bills> info = billsService.getBills(-1, null, null, 1, PageUtil.PAGESIZE);

    // 儲存資料給前臺
    map.addAttribute("types", types);
    map.addAttribute("info", info);

    return "show";
}
@RequestMapping("/getAllBills")
public String getBills(@RequestParam(defaultValue = "1") int index, @RequestParam(defaultValue = "-1") Integer typeid, String begin, String end, ModelMap map){

    PageInfo<Bills> info = billsService.getBills(typeid, begin, end, index, PageUtil.PAGESIZE);
    map.addAttribute("info", info);
    // 資料回顯
    // 將模糊查詢的條件值再返回給前臺
    map.addAttribute("tid", typeid);
    map.addAttribute("begintime", begin);
    map.addAttribute("endtime", end);

    List<Billtype> types = typesService.getTypes();
    map.addAttribute("types", types);

    return "show";
}

其中index被定義為一個常量3

public interface PageUtil {
    public int PAGESIZE = 3;
}

前端頁面:
後臺返回給前端的資料變成PageInfo物件;
要控制點選上一頁,下一頁時顯示的範圍;
分頁查詢的時候記得要帶上模糊查詢的引數;

<%--
  Created by IntelliJ IDEA.
  User: 12291
  Date: 2020/10/30
  Time: 10:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>記賬管理</h1>

<p>
    <form action="/getAllBills" method="post">
    型別:
    <select name="typeid">
        <option value="-1">不限</option>
        <c:forEach items="${types}" var="tp">
            <option value="${tp.id}" ${tid==tp.id?'selected':''}>${tp.bname}</option>
        </c:forEach>
    </select>

    時間:
        從<input type="text" name="begin" value="${begintime}"><input type="text" name="end" value="${endtime}">
        <input type="submit" value="搜尋">
    </form>
        <input type="button" value="記賬">
</p>

<table border="1" width="500">
    <tr>
        <td>標題</td>
        <td>記賬時間</td>
        <td>類別</td>
        <td>金額</td>
        <td>說明</td>
        <td>操作</td>
    </tr>

    <c:if test="${info.list.size() > 0}">
        <c:forEach items="${info.list}" var="bill">
            <tr>
                <td>${bill.title}</td>
                <td><fmt:formatDate value="${bill.billtime}" pattern="yyyy-MM-dd"/></td>
                <td>${bill.billtype.bname}</td>
                <td>
                    <c:choose>
                        <c:when test="${bill.billtype.bname =='支出' || bill.billtype.bname =='借出' || bill.billtype.bname =='還出'}">
                            -${bill.price}
                        </c:when>
                        <c:when test="${bill.billtype.bname =='收入' || bill.billtype.bname =='借入' || bill.billtype.bname =='還入'}">
                            +${bill.price}
                        </c:when>
                        <c:otherwise>
                            ${bill.price}
                        </c:otherwise>
                    </c:choose>
                </td>
                <td>${bill.explains}</td>
                <td>刪除 修改</td>
            </tr>
        </c:forEach>
    </c:if>

    <c:if test="${info.list.size() == 0}">
        <tr>
            <td colspan="6"> <h3>沒有找到任何資料</h3> </td>
        </tr>
    </c:if>

    <tr>
        <td colspan="6">
            <a href="/getAllBills?typeid=${tid}&begin=${begintime}&end=${endtime}">首頁</a>

            <a href="/getAllBills?index=${info.prePage==0?1:info.prePage}&typeid=${tid}&begin=${begintime}&end=${endtime}">上一頁</a>

            <a href="/getAllBills?index=${info.nextPage==0?info.pages:info.nextPage}&typeid=${tid}&begin=${begintime}&end=${endtime}">下一頁</a>

            <a href="/getAllBills?index=${info.pages}&typeid=${tid}&begin=${begintime}&end=${endtime}">尾頁</a>

            總頁數:${info.pages}

            總條數:${info.total}

        </td>
    </tr>

</table>
</body>
</html>

3.4 記賬功能(新增資料)

前端頁面:
注意,頁面中的name要和後臺Bill類的屬性名一致

<%--
  Created by IntelliJ IDEA.
  User: 12291
  Date: 2020/10/30
  Time: 16:52
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>記賬</h1>
    <form action="/insertBill" method="post">
<p>型別:
    <c:forEach items="${types}" var="ty">
        <input type="radio" value="${ty.id}" name="typeid">${ty.bname}
    </c:forEach>
</p>
<p>標題:<input type="text" style="width: 500px" name="title"></p>
<p>日期:<input type="text" name="billtime">金額:<input type="text" name="price"></p>
<p>說明:<textarea cols="50" rows="4" name="explains"></textarea></p>
        <input type="reset" value="重置">
        <input type="submit" value="儲存">
    </form>
</body>
</html>

dao層的程式碼是自動生成的,所以已經有了insert方法,直接從service層開始寫:
BillsService中新增:

public int insert(Bills record);

實現類,注意要開啟事務:

@Override
@Transactional
public int insert(Bills record) {
    return billsMapper.insert(record);
}

controller:

@RequestMapping("/insertBill")
public String add(Bills bills){
    int insert = billsService.insert(bills);
    if (insert > 0){
        // 回到主頁面
        return "redirect:/gettypes";
    }
    // 回到新增頁面
    return "redirect:/getBillType";
}

測試的時候需要注意,由於採用的是預設springMVC日期輸入格式,所以需要的是2020/2/2這種以斜槓分割的方式。

3.5 更新賬單

更新賬單其實分了兩個操作,一個是查詢賬單,一個是修改賬單

3.5.1 查詢賬單

show.jsp中為修改操作新增a標籤

<a href="/findById?bid=${bill.id}">修改</a>

controller定義對應方法:

@RequestMapping("/findById")
public String findById(int bid, ModelMap map){
    Bills bills = billsService.selectByPrimaryKey(bid);
    List<Billtype> types = typesService.getTypes();
    map.addAttribute("bills", bills);
    map.addAttribute("types", types);
    return "update";
}

service層:
介面:

Bills selectByPrimaryKey(Integer id);

實現類:

@Override
public Bills selectByPrimaryKey(Integer id) {
    return billsMapper.selectByPrimaryKey(id);
}

dao是自動生成的:

<sql id="Base_Column_List">
  id, title, billtime, typeid, price, explains
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
  select 
  <include refid="Base_Column_List" />
  from bills
  where id = #{id,jdbcType=INTEGER}
</select>

前端介面:
controller會返回一個update.jsp頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>更新</h1>
    <form action="/updateBill" method="post">
        <input type="hidden" name="id" value="${bills.id}">
        <p>型別:
            <c:forEach items="${types}" var="ty">
                <input type="radio" value="${ty.id}" ${ty.id==bills.typeid?"checked":""} name="typeid">${ty.bname}
            </c:forEach>
        </p>
        <p>標題:<input type="text" style="width: 500px" name="title" value="${bills.title}"></p>
        <p>日期:<input type="text" name="billtime" value="<fmt:formatDate value="${bills.billtime}" pattern="yyyy/MM/dd"/>">金額:<input type="text" name="price" value="${bills.price}"></p>
        <p>說明:<textarea cols="50" rows="4" name="explains">${bills.explains}</textarea></p>
        <input type="reset" value="重置">
        <input type="submit" value="儲存">
    </form>
</body>
</html>

3.5.2 修改操作

controller:

@RequestMapping("/updateBill")
public String updateBill(Bills bills){
    int i = billsService.updateByPrimaryKey(bills);
    if (i > 0){
        return "redirect:/gettypes";
    }
    return "redirect:/findById?bid=" + bills.getId();
}

修改成功返回show頁面,修改失敗返回update頁面。

service層:

@Override
public int updateByPrimaryKey(Bills record) {
    return billsMapper.updateByPrimaryKey(record);
}

dao也是自動生成的:

<update id="updateByPrimaryKey" parameterType="com.wangjiawei.bean.Bills">
  update bills
  set title = #{title,jdbcType=VARCHAR},
    billtime = #{billtime,jdbcType=DATE},
    typeid = #{typeid,jdbcType=INTEGER},
    price = #{price,jdbcType=DOUBLE},
    explains = #{explains,jdbcType=VARCHAR}
  where id = #{id,jdbcType=INTEGER}
</update>

3.5.3 刪除操作

show.jsp中為刪除新增一個按鈕

<a href="/deleteById?bid=${bill.id}">刪除</a>

controller層:
新增刪除方法

@RequestMapping("/deleteById")
public void delete(int bid, HttpServletResponse response){
    int i = billsService.deleteByPrimaryKey(bid);
    response.setContentType("text/html;charset=utf-8");
    try {
        PrintWriter writer  = response.getWriter();
        if (i > 0){
            writer.print("<script>alert('刪除成功');location.href='/gettypes'</script>");
            return;
        }
        writer.print("<script>alert('刪除失敗');location.href='/gettypes'</script>");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

service層:
介面

public int deleteByPrimaryKey(Integer id);

實現類

@Override
@Transactional
public int deleteByPrimaryKey(Integer id) {
    return billsMapper.deleteByPrimaryKey(id);
}

關於原始碼:
  大家可以通過我的下載主業進行下載,或者公眾號裡由有我個人的聯絡方式
在這裡插入圖片描述

相關文章