Spring Boot、MyBatis、Thymeleaf 简单增删改查

Spring Boot、MyBatis、Thymeleaf 简单增删改查

源码地址:https://gitee.com/Azure_Sky/SpringStudy.git

一、创建项目

1。新建项目

二、创建数据库及数据表

数据库名为thymeleaf、数据表名称db_article各字段如下

三、配置数据库连接信息,在application.properties文件中配置数据库连接信息

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/thymeleaf?UseUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.thymeleaf.cache=false

四、在resources下新建mybatis.cfg.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>
    <!--引入外部配置文件-->
    <properties resource="application.properties"></properties>
    <!--为Java Bean起类别名-->
    <typeAliases>
        <package name="com.example.demo.beans"></package>
    </typeAliases>

    <!--配置mybatis运行环境-->
    <environments default="mybatis">
        <environment id="mybatis">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${spring.datasource.driver-class-name}"></property>
                <property name="url" value="${spring.datasource.url}"></property>
                <property name="username" value="${spring.datasource.username}"></property>
                <property name="password" value="${spring.datasource.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com/example/demo/mapper"></package>
    </mappers>
</configuration>

五、在java下的com.example.demo下创建如下包

beans存放实体类,controller存放控制器,mapper存放mybatis映射文件与接口文件,service存放事务类,tools存放工具类,DemoApplication为启动类

1.在beans下新建实体类(Article类),代码如下:

package com.example.demo.beans;

import java.util.Date;

public class Article {
    private int id;
    private String title;
    private String author;
    private String content;
    private Date createdate;

    //省略set和get方法
}

2.在mapper下新建ArticleMapper接口,内容如下:

package com.example.demo.mapper;

import com.example.demo.beans.Article;

import java.util.List;

public interface ArticleMapper {
    /**
     * 查询所有的文章信息
     * @return 所有的文章信息
     * @throws Exception
     */
    public List<Article> selectAllArticle() throws Exception;


    /**
     * 添加文章
     * @param article 添加的文章信息
     * @return 添加成功后的文章信息
     * @throws Exception
     */
    public int addArticle(Article article) throws Exception;

    /**
     * 编辑文章信息
     * @param article 编辑后的文章信息
     * @return 成功返回true、否则返回false
     * @throws Exception
     */
    public int editArticle(Article article) throws Exception;

    /**
     * 根据文章id删除文章信息
     * @param id 文章id
     * @return 成功返回true,否则返回false
     * @throws Exception
     */
    public int deleteArticle(int id) throws Exception;

    /**
     * 根据文章id取得文章信息
     * @param id 文章id
     * @return 返回文章信息
     * @throws Exception
     */
    public Article getArticleById(int id) throws Exception;
}

在mapper下新建ArticleMapper.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.example.demo.mapper.ArticleMapper">
    <!--自定义返回结果集-->
    <resultMap id="articleMap" type="Article">
        <id property="id" column="id" javaType="java.lang.Integer"/>
        <result property="title" column="title" javaType="java.lang.String"/>
        <result property="author" column="author" javaType="java.lang.String"/>
        <result property="content" column="content" javaType="java.lang.String"/>
        <result property="createdate" column="createdate" javaType="java.util.Date"/>
    </resultMap>

    <select id="selectAllArticle" resultMap="articleMap">
        select * from tb_article
    </select>

    <insert id="addArticle" parameterType="com.example.demo.beans.Article"
            useGeneratedKeys="true" keyProperty="id">
        insert into tb_article(title,author,content,createdate)
        values(#{title},#{author},#{content},#{createdate})
    </insert>

    <update id="editArticle" parameterType="com.example.demo.beans.Article">
        update tb_article set title=#{title},author=#{author}
        ,content=#{content},createdate=#{createdate} where id=#{id}
    </update>

    <delete id="deleteArticle">
        delete from tb_article where id=#{id}
    </delete>


    <select id="getArticleById" parameterType="int" resultType="com.example.demo.beans.Article">
        select * from tb_article where id=#{id}
    </select>
</mapper>

3.在service下新建ArticleService类,内容如下:

package com.example.demo.service;

import com.example.demo.beans.Article;
import com.example.demo.mapper.ArticleMapper;
import com.example.demo.tools.DBTools;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class ArticleService {
    /**
     * 取得所有文章信息
     * @return 所有文章信息集合
     */
    public List<Article> getAllArticles(){
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);
        List<Article> articles=null;
        try {
            articles=mapper.selectAllArticle();
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }finally{
            session.close();
        }
        return articles;
    }


    /**
     * 发表文章
     * @param article 发表的文章信息
     * @return 如果发表成功,返回true,否则返回false
     */
    public boolean addArticle(Article article){
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);

        int result=0;
        try {
            result=mapper.addArticle(article);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }finally{
            session.close();
        }
        if(result>0){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 根据文章ID取得文章内容
     * @param id 文章id
     * @return 文章实体类对象
     */
    public Article getArticleById(int id){
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);

        Article article=null;
        try {
            article=mapper.getArticleById(id);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
        }finally{
            session.close();
        }
        return article;
    }

    /**
     * 根据Id删除文章信息
     * @param id 欲删除文章的id
     * @return 如果删除成功,返回true,否则返回false
     */
    public boolean deleteArticleById(int id){
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);

        int result=0;
        try {
            result=mapper.deleteArticle(id);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }finally{
            session.close();
        }
        return result>0;
    }


    /**
     * 编辑文章信息
     * @param article 修改后的文章信息
     * @return 如果编辑成功,返回true,否则返回false
     */
    public boolean editArticle(Article article){
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);

        int result=0;
        try {
            result=mapper.editArticle(article);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }finally{
            session.close();
        }

        return result>0;
    }

}

4.在tools下新建DBTools类,用于获得SqlSession对象,内容如下:

package com.example.demo.tools;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;


import java.io.IOException;
import java.io.Reader;

public class DBTools {
    private static SqlSessionFactory sessionFactory;
    static{
        try {
            Reader reader= Resources.getResourceAsReader("mybatis.cfg.xml");
            sessionFactory=new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSession(){
        return sessionFactory.openSession();
    }
}

5.在controller下新建ArticleController控制器,代码如下:

package com.example.demo.controller;

import com.example.demo.beans.Article;
import com.example.demo.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Date;
import java.util.List;

@Controller
public class ArticleController {
    @Autowired
    private ArticleService articleService;

    /**
     * 显示所有的文章信息
     * @param model 传递给View的数据
     * @return View视图
     */
    @RequestMapping("/article")
    public String showArtiles(Model model){
        List<Article> articles=articleService.getAllArticles();
        model.addAttribute("articles",articles);
        return "/article/index";
    }



    /**
     * 调用发表文章视图
     * @return 发表文章视图页面
     */
    @RequestMapping(value="/createArticle",method = RequestMethod.GET)
    public String create(){
        return "/article/create";
    }

    /**
     * 发表文章逻辑,将文章信息保存到数据库中
      * @param article 发表文章视图传递过来的文章信息
     * @return 所有文章列表页
     */
    @RequestMapping(value = "/saveArticle",method = RequestMethod.POST)
    public String create(Article article){
        article.setCreatedate(new Date());
        if(articleService.addArticle(article)){
            return "redirect:/article";//跳转到文章列表页
        }else{
            return "/article/create";
        }
    }


    /**
     * 文章详细内容页
     * @param id 文章的ID
     * @return 返回文章的详细内容
     */
    @RequestMapping(value = "/details/{id}",method = RequestMethod.GET)
    public String details(@PathVariable("id") int id, Model model){
        Article article=articleService.getArticleById(id);
        model.addAttribute("article",article);
        return "/article/details";
    }

    /**
     * 删除文章
     * @param id 欲删除文章的id
     * @return 如果删除成功,返回到文章列表页,不成功也返回到文章列表页
     */
    @RequestMapping(value="/delete/{id}",method = RequestMethod.GET)
    public String deleteArticle(@PathVariable("id") int id){
        if(articleService.deleteArticleById(id)){
            return "redirect:/article";//跳转到文章列表页
        }
        return "redirect:/article";
    }

    /**
     * 编辑文章信息
     * @param id 欲编辑文章的id
     * @param model 欲编辑文章的信息,用于在视图中进行显示
     * @return 编辑文章的视图表单
     */
    @RequestMapping(value="/edit/{id}",method = RequestMethod.GET)
    public String edit(@PathVariable("id") int id,Model model){
        Article article=articleService.getArticleById(id);
        model.addAttribute("article",article);
        return "/article/edit";
    }

    /**
     * 编辑文章逻辑 将修改后的文章信息更新到数据库
     * @param article
     * @return
     */
    @RequestMapping(value = "/updateArticle",method = RequestMethod.POST)
    public String edit(Article article,Model model){
        if(articleService.editArticle(article)){
            return "redirect:/article";//跳转到文章列表页
        }
        model.addAttribute("article",article);
        return "/article/edit";
    }

    @RequestMapping("/")
    @ResponseBody
    public String hello(){
        return "Hello thymeleaf";
    }

    @RequestMapping("/test")
    public String testLayout(){
        return "/test";
    }
}

六、创建视图层`

resources下下目录结构如下:

1.引入BootStrap、jQuery

在static下新建bootstrap,将下载到的bootstrap文件下的css、fonts、js目录复制到bootstrap目录下,将jQuery文件复制到js目录下,

2.在templates下创建article和common两个目录

article目录用于存放article的所有视图    

common用于存放布局页面

3.在common下创建布局页,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${title}">Title</title>

    <!--引入BootsStrap样式-->
    <link rel="stylesheet" type="text/css"
          th:href="@{/bootstrap/css/bootstrap.css}">

    <!--引入自定义样式-->
    <link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/main.css}">

    <!--引入js文件-->
    <script th:src="@{/bootstrap/js/jquery.min.js}"></script>
    <script th:src="@{/bootstrap/js/bootstrap.js}"></script>

</head>
<body>
<!--最外层容器-->
<div id="wrap" class="container">
    <!--页面头部-->
    <header>
        <nav class="navbar navbar-default">
            <div class="container-fluid">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Brand</a>
                </div>

                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                        <li class="active">
                            <a href="#" th:href="@{/}">首页</a>
                        </li>
                        <li><a href="#" th:href="@{/test}">测试</a></li>
                        <li><a href="#" th:href="@{/article}">技术文章</a></li>
                    </ul>
                    <form class="navbar-form navbar-right">
                        <div class="form-group">
                            <input type="text" class="form-control" placeholder="请输入文章名">
                        </div>
                        <button type="submit" class="btn btn-default">Search</button>
                    </form>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </nav>
    </header>
    <!-- 页面主体部分-->
    <div id="main_content" th:include="::main_content">

    </div>
    <!--页面底部-->
    <footer class="row">
        <div class="col-md-12">
            <ul>
                <li><a href="#">GitHub仓库地址</a></li>
                <li><a th:href="@{http://www.my.oschina.net/u/3537796/blog}">博客</a></li>
                <li><a th:href="@{http://www.bootcss.com}">BootStrap</a></li>
                <li><a th:href="@{http://www.w3school.com.cn/jquery}">jQueryfttk</a></li>
            </ul>
        </div>
        <div class="col-md-12">
            <p>
                CopyRight:BlueMonkey 地址:中国河南
            </p>
        </div>
    </footer>
</div>
</body>
</html>

4.在article目录下,新建index.html文件,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      th:replace="common/layout(title='测试布局')">

<div th:fragment="main_content">
    <table class="table table-hover">
        <tr>
            <td>编号</td>
            <td>标题</td>
            <td>发表日期</td>
            <td></td>
        </tr>
        <tr th:each="article:${articles}">
            <td th:text="${article.getId()}"></td>
            <td th:text="${article.getTitle()}"></td>
            <td th:text="${article.getCreatedate()}"></td>
            <td>
                <a th:href="@{'/edit/'+${article.getId()}}">编辑文章</a>
                <a th:href="@{'/details/'+${article.getId()}}">文章内容</a>
                <a th:href="@{'/delete/'+${article.getId()}}" onclick="alert('确定要删除文章吗?')">删除文章</a>
            </td>
        </tr>
    </table>
</div>
</html>

5.在article下新建details.html文件,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      th:replace="common/layout(title='测试布局')">

<div th:fragment="main_content">
    <article class="text-center">
        <h3 th:text="${article.getTitle()}"></h3>
        <h4 th:text="${article.getAuthor()}"></h4>
        <p th:text="${article.getContent()}" class="text-left"></p>
        <h4 th:text="${article.getCreatedate()}" class="text-right"></h4>
    </article>
</div>
</html>

6.在article下新建create.html文件,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
    th:replace="common/layout(title='发表文章')">
    <!--发表文章信息表单-->
    <div th:fragment="main_content">
        <form action="/saveArticle" method="post">
            文章标题:<input type="text" name="title"><br/><br/>
            作者名称:<input type="text" name="author"><br/><br/>
            文章内容:<input type="text" name="content"><br/><br/>
            <input type="submit" value="确定">
        </form>

    </div>
</html>

7.在article目录下,新建edit.html文件,内容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      th:replace="common/layout(title='编辑文章')">
<!--发表文章信息表单-->
<div th:fragment="main_content">
    <form action="/updateArticle" method="post">
        <input type="hidden" name="id" th:value="${article.getId()}">
        <input type="hidden" name="createdate" th:value="${article.getCreatedate()}">
        文章标题:<input type="text" name="title" th:value="${article.getTitle()}"><br/><br/>
        作者名称:<input type="text" name="author" th:value="${article.getAuthor()}"><br/><br/>
        文章内容:<input type="text" name="content" th:value="${article.getContent()}"><br/><br/>
        <input type="submit" value="确定">
    </form>
</div>
</html>

七、运行结果

八、补充搜索文章

1.修改mapper下的ArticleMapper接口,添加如下代码

/**
     * 根据文章标题查询文章信息
     * @param title
     * @return 查询到的文章信息
     * @throws Exception
     */
    public List<Article> getArticleByTitle(String title) throws Exception;

2.修改ArticleMapper.xml文件,添加如下配置

<select id="getArticleByTitle" parameterType="String" resultMap="articleMap">
        select * from tb_article where title like "%"#{title}"%"
    </select>

3.修改service下的ArticleService

/**
     * 查找文章,根据标题模糊查找
     * @param title 文章标题
     * @return 如果有返回相应的文章信息,无则返回null
     */
    public List<Article> searchArticleByTitle(String title){
        List<Article> articles=null;
        SqlSession session=DBTools.getSession();
        ArticleMapper mapper=session.getMapper(ArticleMapper.class);

        try {
            articles=mapper.getArticleByTitle(title);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            session.close();
        }
        return articles;
    }

4.修改controller下的ArticleController类,

/**
     * 查找文章,根据标题模糊
     * @param title 标题
     * @param model 返回数据
     * @return 如果不为空返回数据,为空返回错误页
     */
    @RequestMapping(value = "/searchArticle",method = RequestMethod.POST)
    public String searchArticle(String title,Model model){
        List<Article> articles=articleService.searchArticleByTitle(title);
        if(!articles.isEmpty()){
            model.addAttribute("articles",articles);
            return "/article/searchResult";
        }else{
            model.addAttribute("info","没有你要查找的结果");
            return "/common/error";
        }
    }

5.在resources下templates下的article下,新建searchResult.html文件,

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      th:replace="common/layout(title='测试布局')">

<div th:fragment="main_content">
    <table class="table table-hover">
        <tr>
            <td>编号</td>
            <td>标题</td>
            <td>发表日期</td>
            <td></td>
        </tr>
        <tr th:each="article:${articles}">
            <td th:text="${article.getId()}"></td>
            <td th:text="${article.getTitle()}"></td>
            <td th:text="${article.getCreatedate()}"></td>
        </tr>
    </table>
</div>
</html>

6.在common下新建error.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      th:replace="common/layout(title='测试布局')">

<div th:fragment="main_content">
    <h3 th:text="${info}">错误消息</h3>
</div>
</html>

猜你喜欢

转载自my.oschina.net/u/3537796/blog/1827039