J2EE项目系列(二)--博客管理系统(Maven+SpringMVC+Hibernate以及附加分页和一对多查询功能)

很抱歉,同时写几个系列并且本人在考试月,真的有点忙不过来,也要复习一些考试知识,所以更新得有点慢,但我会坚持更新这些系列的。请大家放心。今天要更的是Maven+SpringMVC+Hibernate的项目并附带分页功能以及一对多查询功能。


文章结构:
1.项目介绍(功能业务逻辑,运用的知识,项目数据库等);
2.项目架构介绍以及部分关键逻辑代码说明(分页以及一对多查询功能的实现(通过PagingAndSortingRepository实现))。
3.源码分享。


本系列:J2EE项目系列

一、 J2EE项目系列(一)–学生管理系统


一、项目介绍(功能业务逻辑,运用的知识,项目数据库等)

(1)功能介绍
1.添加管理账号,包括账号、密码,你的名字(新旧名字)。还有一系列的增删改查。
2.添加博客文章,文章的日期、内容、标题、id。还有一系列的增删改查。
3.实现外键级联属性
4.实现分页查询统计
5.实现一对多查询
6.部分前端代码,基于bootstrap的样式和js.min
(2)运用的知识
使用Intellij进行开发的,spring,hibernate,mysql,maven
1.基本数据库知识MySQL
2.SpringMVC+hibernate
3.(重点)框架的MVC设计模式的应用
4.(重点)分页查询
5.(重点)一对多查询
6.部分前端代码,基于bootstrap的样式和js.min以及一些jstl
7.JpaRepository的使用
(3)项目构建:使用Maven快速构建项目
给出maven代码并讲解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:mvc="http://www.springframework.org/schema/mvc"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fuzhu</groupId>
    <artifactId>springmvcdemo</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>springmvcdemo Maven Webapp</name>
    <url>http://maven.apache.org</url>
	<!--springcore的。虽然我们只写了一个依赖,但是它导入了两个jar包,也就是说,导入某个jar包时,与它密切相关的jar包也会同时被导入进来。-->
	
    <properties>
        <spring.version>4.2.6.RELEASE</spring.version>
        <hibernate.version>5.1.0.Final</hibernate.version>
    </properties>

    <dependencies>
		<!--servlet的-->
        <dependency>
            <groupId>org.jboss.spec.javax.servlet</groupId>
            <artifactId>jboss-servlet-api_3.1_spec</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>tjws</artifactId>
            <version>3.0.10.Final</version>
            <scope>test</scope>
        </dependency>
		<!--junit单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
		<!--SpringMVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
		<!--spring基本包-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.10.1.RELEASE</version>
        </dependency>
	<!--hibernate基本包-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.0.8</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.6</version>
        </dependency>

    </dependencies>
    <build>
        <finalName>springmvcdemo</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
(4)项目分包:MVC架构。对比我的上一篇项目,使用框架的优势就完美体现出来了。极度精简的代码,项目代码设计。

这里写图片描述

(5)数据库:
//user表
CREATE TABLE user(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nickname VARCHAR(45) NOT NULL,
password VARCHAR(45) NOT NULL,
first_name VARCHAR(45),
last_name VARCHAR(45)
);
//blog表
CREATE TABLE blog(
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100),
content VARCHAR(100),
user_id INT(11) UNSIGNED,
pub_date DATE
);
大家需要使用工具去添加外键,我就这样偷懒了。哈哈
添加外键 user_id--id


测试数据:
INSERT INTO `t2`.`blog` (`title`, `content`, `user_id`, `pub_date`) VALUES ('发发发方法付', '发发发方法付付付', '1', '2016-12-29');
INSERT INTO `t2`.`user` (`nickname`, `password`, `first_name`, `last_name`) VALUES ('fuzhu', '75111', 'fuzh', 'fuzhu');
(6)项目功能截图:

下面是用户表的增删改查

这里写图片描述

下面是实现一对多的查询

这里写图片描述

下面是博客文章的总表,并实现分页查询

这里写图片描述


二、项目架构介绍以及部分关键逻辑代码说明

基本的MVC架构了,model-view-controller

大家学习持久层开发的时候可以使用JpaRepository。本博客也是使用这个。这个是详细文档Spring Data

此分层的结构:(注意篇)项目一些坑以及配置过程(1)user业务逻辑的的接口;(2)blog业务的逻辑接口;(3)分页功能的接口;(4)细讲分页功能(含JpaRepository使用);(5)细讲一对多查询功能(含JpaRepository使用)

(注意篇)项目一些坑以及配置过程

(注意篇)1.项目配置系列,大家可根据这篇去配置我们的项目,暂不吐槽他的命名以及一些做法,但还是很详细and很多可取之处的。项目配置。在此感谢那位博主的付出。

(注意篇)2.即使按照他配置,还是有一些坑的。

<%@ page isELIgnored="false" %>
<!--这句代码非常重要!!!必须在jsp中添加,至于加在哪里,大家下载我的项目时候看jsp文件吧-->
<!--JSTL表达式语言可以使用标记格式方便地访问JSP的隐含对象和JavaBeans组件,JSTL的核心标记提供了流程和循环控制功能。自制标记也有自定义函数的功能-->

(注意篇)3.使用JpaRepository开发是有比较多坑的,大家需要先仔细阅读文档Spring Data。我的分页功能和一对多查询功能都是在这里学习的。不过我的是整合成项目,文档的是零散的。

比如jstl的使用,以及注意点,他的那个项目是有些小bug的。

(注意篇)4.注意下面的那个jsp文件里面,在<c:choose>这个标签里面是不支持注释的,用的时候注意把他们删了喔!!

(注意篇)5.大家可能注意到我用到了bootstrep以及js,也许不是单纯后端开发。大家看清楚,这里只是用到他的样式,我们把他删了也是可以的,只不过好看很多而已嘛。

(1)user业务逻辑的的接口
//像我给出的文档中一样,使用JpaRepository接口进行开发持久层
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Integer> {
    @Modifying      // 说明该方法是修改操作
    @Transactional  // 说明该方法是事务性操作
    // 定义查询
    // @Param注解用于提取参数
    @Query("update UserEntity us set us.nickname=:qNickname, us.firstName=:qFirstName, us.lastName=:qLastName, us.password=:qPassword where us.id=:qId")
    public void updateUser(@Param("qNickname") String nickname, @Param("qFirstName") String firstName,
                           @Param("qLastName") String qLastName, @Param("qPassword") String password, @Param("qId") Integer id);
}
(2)blog业务的逻辑接口
public interface BlogRepository extends JpaRepository<BlogEntity,Integer> {
    // 修改博文操作
    @Modifying
    @Transactional
    @Query("update BlogEntity blog set blog.title=:qTitle, blog.userByUserId.id=:qUserId," +
            " blog.content=:qContent, blog.pubDate=:qPubDate where blog.id=:qId")
    void updateBlog(@Param("qTitle") String title, @Param("qUserId") int userId, @Param("qContent") String content,
                    @Param("qPubDate") Date pubDate, @Param("qId") int id);
    //一对多查询方法
    @Query("select blog from BlogEntity blog where blog.userByUserId.id = ?1")
    List<BlogEntity> findByUserByUserId(int userId);
}
(3)分页功能的接口
//可直接装配使用的。
@Repository
public interface BlogPageDao extends PagingAndSortingRepository<BlogEntity, Long> {
}
(4)细讲分页功能(含JpaRepository使用)
	//需要自动装配那几个接口咯
	@Autowired
    BlogRepository blogRepository;
    @Autowired
    UserRepository userRepository;
    @Autowired
    private BlogPageDao districtRepository;
    // 查看所有博文,实现分页查询!!!注意是一个get请求,并且携带参数。
    @RequestMapping(value = "/admin/blogs", method = RequestMethod.GET)
    public String showBlogs(ModelMap modelMap,@RequestParam(value = "pageNonumber", required = false, defaultValue = "0") Integer pageNonumber) {
		 //如果pageNonumber,也就是当前页,要有特殊处理,奇葩的都弄到第一页
        if (pageNonumber== null ||  pageNonumber==-1) {
            pageNonumber= 0;
        }
// pageNonumber是从0开始的,所以我们显示的时候要有特殊处理,这个是从数据库读取出来,不用特别处理
        int pageSize = 5;       //页面包含条数的多少
        // PageRequest接口通常使用的起PageRequest实现类,其中封装了需要分页的信息。
        PageRequest pageRequest = new PageRequest(pageNonumber, pageSize);
        Page<BlogEntity> page = districtRepository.findAll(pageRequest);
        System.out.println("总记录数:" + page.getTotalElements());
        System.out.println("当前第几页:" + page.getNumber());
        System.out.println("总页数" + page.getTotalPages());
        System.out.println("当前页面的list:" + page.getContent());
        System.out.println("当前页面记录数:" + page.getNumberOfElements());

        modelMap.addAttribute("sourceCodeList",page.getContent());  //当前页面的list
        modelMap.addAttribute("totalPageNumber",page.getTotalElements());//总记录数
        modelMap.addAttribute("numberPage",page.getNumber());//当前第几页
        modelMap.addAttribute("totalPages",page.getTotalPages());//总页数

        return "pages/testPage";
    }

下面重点关注分页的几个点:1.传过来要按照map的key对应取值;2.注意sourceCodeList,totalPageNumber,numberPage,totalPages的处理。

<%@ 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>
    <!-- 这个是重点!!!jstl使用获取数据的前提-->
    <%@ page isELIgnored="false" %>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>SpringMVC 博客管理</title>

    <title>分页page</title>
    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">

    <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>


    <![endif]-->

</head>
<body>
<div layout:fragment="content">
    <a href="/admin/blogs" class="list-group-item active">
        你的博客文章
    </a>
    <table class="table table-bordered table-striped">
        <tr>
            <th>ID</th>
            <th>标题</th>
            <th>作者</th>
            <th>发布日期</th>
            <th>操作</th>
        </tr>
        <!--根据key得到的那个sourceCodeList就需要遍历出来,按照他包含的BlogEntitiy去读出来-->
        <c:forEach items="${sourceCodeList}" var="blog">
            <tr>
                <td>${blog.id}</td>
                <td>${blog.title}</td>
                <td>${blog.userByUserId.nickname}, ${blog.userByUserId.firstName} ${blog.userByUserId.lastName}</td>
                <td><fmt:formatDate value="${blog.pubDate }" pattern="yyyy-MM-dd"/></td>
                <td>
                    <a href="/admin/blogs/show/${blog.id}" type="button" class="btn btn-sm btn-success">详情</a>
                    <a href="/admin/blogs/update/${blog.id}" type="button" class="btn btn-sm btn-warning">修改</a>
                    <a href="/admin/blogs/delete/${blog.id}" type="button" class="btn btn-sm btn-danger">删除</a>
                </td>
            </tr>
        </c:forEach>
        <tr>
        <!--这里就是处理那几个传过来的page数据的啦,从而实现分页嘛-->
            <td colspan="6" align="center" bgcolor="#5BA8DE">共${totalPageNumber}条记录 共${totalPages}页
                当前第${numberPage+1}页<br>

                <c:choose>
                 <!--这里处理是,numberPage 当前页不等于0的时候可以点击,也就是等于就点击不了咯-->
                    <c:when test="${numberPage!=0}">
<!--用了链接使用get请求,传想要去的那个页过去,其实就是在当前页上面做文章-->
                        <a href="${path}/admin/blogs?pageNonumber=${numberPage-1}"><input type="button"
                                                                                          name="previousPage"
                                                                                          value="上一页"/></a>

                    </c:when>
                    <c:otherwise>

                        <input type="button" disabled="disabled" name="previousPage" value="上一页"/>

                    </c:otherwise>
                </c:choose>
                <c:choose>
                <!--这里处理是,numberPage 当前页不等于总页数减一的时候可以点击,也就是等于就点击不了咯-->
                    <c:when test="${numberPage != totalPages-1}">
                    <!--用了链接使用get请求,传想要去的那个页过去,其实就是在当前页上面做文章-->
                        <a href="${path}/admin/blogs?pageNonumber=${numberPage+1}"><input type="button" name="nextPage"
                                                                                          value="下一页"/></a>
                    </c:when>
                    <c:otherwise>

                        <input type="button" disabled="disabled" name="nextPage" value="下一页"/>

                    </c:otherwise>
                </c:choose>
            </td>
        </tr>
    </table>

</div>

<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
这样就实现一个分页功能啦!!!

(5)细讲一对多查询功能(含JpaRepository使用):

//使用这个接口实现分页查询开发
public interface BlogRepository extends JpaRepository<BlogEntity,Integer> {
    // 修改博文操作
    @Modifying
    @Transactional
    @Query("update BlogEntity blog set blog.title=:qTitle, blog.userByUserId.id=:qUserId," +
            " blog.content=:qContent, blog.pubDate=:qPubDate where blog.id=:qId")
    void updateBlog(@Param("qTitle") String title, @Param("qUserId") int userId, @Param("qContent") String content,
                    @Param("qPubDate") Date pubDate, @Param("qId") int id);
    //一对多查询方法。我们要注意这个接口方法语句的拼接,很重要。
    //blog.userByUserId.id 特别是这里,指的是user的id不是别的id
    @Query("select blog from BlogEntity blog where blog.userByUserId.id = ?1")
    List<BlogEntity> findByUserByUserId(int userId);
}

//功能:一对多的查询,查询自己的博客文章
    @RequestMapping(value = "/admin/users/blogsDetails/{id}",method = RequestMethod.GET)
    public String lookBlogs(ModelMap modelMap,@PathVariable("id") Integer userId){
    //注意那个传过来的id
        List<BlogEntity>blogEntityList = blogRepository.findByUserByUserId(userId);
        for (BlogEntity blog :blogEntityList){
            System.out.println("博客的啊啊啊啊啊啊"+blog.getId());
            System.out.println(blog.getContent());
            System.out.println(blog.getPubDate());
        }
        modelMap.addAttribute("blogList", blogEntityList);
        return "admin/blogs";
    }

下面是显示查询到的博客文章嘛,没啥特别的

<%--
  Created by IntelliJ IDEA.
  User: 符柱成
  Date: 2016/12/29
  Time: 21: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" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <!-- 这个是重点!!!jstl使用获取数据的前提-->
    <%@ page isELIgnored="false" %>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>SpringMVC 博客管理</title>

    <!-- 新 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">

    <![endif]-->
</head>
<body>
<div class="container">
    <h1>SpringMVC 博客系统-博客管理</h1>
    <hr/>

    <h3>所有博客 <a href="/admin/blogs/add" type="button" class="btn btn-primary btn-sm">添加</a></h3>

    <!-- 如果用户列表为空 -->
    <c:if test="${empty blogList}">
        <div class="alert alert-warning" role="alert">
            <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>Blog表为空,请<a href="/admin/blogs/add"
                                                                                              type="button"
                                                                                              class="btn btn-primary btn-sm">添加</a>
        </div>
    </c:if>

    <!-- 如果用户列表非空 -->
    <c:if test="${!empty blogList}">
        <table class="table table-bordered table-striped">
            <tr>
                <th>ID</th>
                <th>标题</th>
                <th>作者</th>
                <th>发布日期</th>
                <th>操作</th>
            </tr>

            <c:forEach items="${blogList}" var="blog">
                <tr>
                    <td>${blog.id}</td>
                    <td>${blog.title}</td>
                    <td>${blog.userByUserId.nickname}, ${blog.userByUserId.firstName} ${blog.userByUserId.lastName}</td>
                    <td><fmt:formatDate value="${blog.pubDate }" pattern="yyyy-MM-dd"/></td>
                    <td>
                        <a href="/admin/blogs/show/${blog.id}" type="button" class="btn btn-sm btn-success">详情</a>
                        <a href="/admin/blogs/update/${blog.id}" type="button" class="btn btn-sm btn-warning">修改</a>
                        <a href="/admin/blogs/delete/${blog.id}" type="button" class="btn btn-sm btn-danger">删除</a>
                    </td>
                </tr>
            </c:forEach>
        </table>
    </c:if>
</div>


<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

三、源码分享

我会给我的源码给大家,大家想用就用吧。哈哈。喜欢就给个star咯,谢谢大家。

Github地址–源码传送门

结语

J2EE项目系列(二)–博客管理系统(Maven+SpringMVC+Hibernate以及附加分页和一对多查询功能)讲完了,这是J2EE项目系列(二),这个系列我会继续写的,分享经验给大家。欢迎在下面指出错误,共同学习!!你的star是对我最好的支持!!

转载请注明:【JackFrost的博客】

更多内容,可以访问JackFrost的博客

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值