1、开发数据层(DAO层)
package ex.book.model;
import java.math.BigDecimal;
import java.util.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
*
* This class was generated by MyBatis Generator.
* This class corresponds to the database table book_info
*/
public class BookInfo {
/**
* 图书编号(id)
*/
private Long id;
/**
* 书名(book_name)
*/
@NotBlank(message = "书名不能为空")
private String bookName;
/**
* 作者(book_author)
*/
@NotBlank(message = "作者不能为空")
private String bookAuthor;
/**
* 条形码(book_isbn)
*/
@NotBlank(message = "条形码不能为空")
private String bookIsbn;
/**
* 价格(book_price)
*/
@NotNull(message = "价格不能为空")
private BigDecimal bookPrice;
/**
* 出版社(publishing)
*/
@NotBlank(message = "出版社不能为空")
private String publishing;
/**
* 创建时间(create_time)
*/
private Date createTime;
/**
* 最后更新时间(last_updated_time)
*/
private Date lastUpdatedTime;
// setter and getter
}
<!-- 条件查询(当条件为空时查询全部) -->
<select id="selectByCondition" resultMap = "BaseResultMap">
select <include refid="Base_Column_List" />
from book_info
<where>
<if test="bookName != null and bookName != ''">
<bind name="nameLike" value="'%' + bookName + '%'" />
and book_name like #{nameLike}
</if>
<if test="bookIsbn != null and bookIsbn != ''">
<bind name="isbnLike" value="'%' + bookIsbn + '%'" />
and book_isbn like #{isbnLike}
</if>
</where>
</select>
/**
* 条件查询(当条件为空时查询全部)
* @return
*/
List<BookInfo> selectByCondition(BookInfo bookInfo);
-
修改BookInfoMapper.xml中的updateByPrimaryKey、updateByPrimaryKeySelective、insert和insertSelective方法,更新或插入时自动获取创建时间和最后更新时间,如下
updateByPrimaryKey
<update id="updateByPrimaryKey" parameterType="ex.book.model.BookInfo">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
update book_info
set book_name = #{bookName,jdbcType=VARCHAR},
book_author = #{bookAuthor,jdbcType=VARCHAR},
book_isbn = #{bookIsbn,jdbcType=VARCHAR},
book_price = #{bookPrice,jdbcType=DECIMAL},
publishing = #{publishing,jdbcType=VARCHAR},
last_updated_time = SYSDATE()
where id = #{id,jdbcType=BIGINT}
</update>
updateByPrimaryKeySelective
<update id="updateByPrimaryKeySelective" parameterType="ex.book.model.BookInfo">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
update book_info
<set>
<if test="bookName != null">
book_name = #{bookName,jdbcType=VARCHAR},
</if>
<if test="bookAuthor != null">
book_author = #{bookAuthor,jdbcType=VARCHAR},
</if>
<if test="bookIsbn != null">
book_isbn = #{bookIsbn,jdbcType=VARCHAR},
</if>
<if test="bookPrice != null">
book_price = #{bookPrice,jdbcType=DECIMAL},
</if>
<if test="publishing != null">
publishing = #{publishing,jdbcType=VARCHAR},
</if>
last_updated_time = SYSDATE()
</set>
where id = #{id,jdbcType=BIGINT}
</update>
insert
<insert id="insert" parameterType="ex.book.model.BookInfo">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into book_info (id, book_name, book_author,
book_isbn, book_price, publishing,
create_time, last_updated_time)
values (#{id,jdbcType=BIGINT}, #{bookName,jdbcType=VARCHAR}, #{bookAuthor,jdbcType=VARCHAR},
#{bookIsbn,jdbcType=VARCHAR}, #{bookPrice,jdbcType=DECIMAL}, #{publishing,jdbcType=VARCHAR},
SYSDATE(), SYSDATE())
</insert>
insertSelective
<insert id="insertSelective" parameterType="ex.book.model.BookInfo">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into book_info
<trim prefix="(" suffix=")" suffixOverrides=",">
id,
<if test="bookName != null">
book_name,
</if>
<if test="bookAuthor != null">
book_author,
</if>
<if test="bookIsbn != null">
book_isbn,
</if>
<if test="bookPrice != null">
book_price,
</if>
<if test="publishing != null">
publishing,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="lastUpdatedTime != null">
last_updated_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
#{id,jdbcType=BIGINT},
<if test="bookName != null">
#{bookName,jdbcType=VARCHAR},
</if>
<if test="bookAuthor != null">
#{bookAuthor,jdbcType=VARCHAR},
</if>
<if test="bookIsbn != null">
#{bookIsbn,jdbcType=VARCHAR},
</if>
<if test="bookPrice != null">
#{bookPrice,jdbcType=DECIMAL},
</if>
<if test="publishing != null">
#{publishing,jdbcType=VARCHAR},
</if>
SYSDATE(), SYSDATE()
</trim>
</insert>
2、开发业务层(Service层)
package ex.book.service;
import java.util.List;
import ex.book.model.BookInfo;
/**
* 图书信息CRUD服务层接口
* @author huangqh
*
*/
public interface BookService {
/**
* 根据图书编号查询图书信息
* @param id
* @return
*/
BookInfo findById(Long id);
/**
* 条件查询(当条件为空时查询全部)
* @param bookInfo
* @return
*/
List<BookInfo> selectByCondition(BookInfo bookInfo);
/**
* 保存或更新图书信息
* @param bookInfo
* @return
*/
boolean saveOrUpdate(BookInfo bookInfo);
/**
* 根据图书编号删除
* @param id
* @return
*/
boolean deleteById(Long id);
}
package ex.book.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import ex.book.mapper.BookInfoMapper;
import ex.book.model.BookInfo;
import ex.book.service.BookService;
/**
* 图书CRUD服务实现类
* @author huangqh
*
*/
@Service("BookService")
public class BookServiceImpl implements BookService {
// spring自动注入服务BookInfoMapper
@Resource
private BookInfoMapper bookMapper;
@Override
public BookInfo findById(Long id) {
return bookMapper.selectByPrimaryKey(id);
}
@Override
public List<BookInfo> selectByCondition(BookInfo bookInfo) {
return bookMapper.selectByCondition(bookInfo);
}
@Override
public boolean saveOrUpdate(BookInfo bookInfo) {
// 获取图书编号
Long id = bookInfo.getId();
// id为空时,为插入,否则为更新
if (id == null) {
return bookMapper.insert(bookInfo) == 1;
} else {
return bookMapper.updateByPrimaryKeySelective(bookInfo) == 1;
}
}
@Override
public boolean deleteById(Long id) {
return bookMapper.deleteByPrimaryKey(id) == 1;
}
}
package book;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import ex.book.model.BookInfo;
import ex.book.service.BookService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class BookMapperTest {
// 日志组件
private static Logger logger = Logger.getLogger(BookMapperTest.class);
@Resource
private BookService bookService;
@Test
public void findById() {
logger.info("findById = " + bookService.findById(1L));
}
@Test
public void selectByCondition() {
BookInfo info = new BookInfo();
info.setBookIsbn("302");
logger.info("selectByCondition = " + bookService.selectByCondition(info));
}
}
[org.springframework.test.context.support.DefaultTestContextBootstrapper] - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
[org.springframework.test.context.support.DefaultTestContextBootstrapper] - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@4439f31e, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@5dfcfece, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@23ceabc1, org.springframework.test.context.support.DirtiesContextTestExecutionListener@5d5eef3d, org.springframework.test.context.transaction.TransactionalTestExecutionListener@56f4468b, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6cc4c815]
[org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [applicationContext.xml]
[org.springframework.context.support.GenericApplicationContext] - Refreshing org.springframework.context.support.GenericApplicationContext@13deb50e: startup date [Sat Nov 10 21:49:21 CST 2018]; root of context hierarchy
[org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
[ex.book.mapper.BookInfoMapper.selectByPrimaryKey] - ==> Preparing: select id, book_name, book_author, book_isbn, book_price, publishing, create_time from book_info where id = ?
[ex.book.mapper.BookInfoMapper.selectByPrimaryKey] - ==> Parameters: 1(Long)
[ex.book.mapper.BookInfoMapper.selectByPrimaryKey] - <== Columns: id, book_name, book_author, book_isbn, book_price, publishing, create_time
[ex.book.mapper.BookInfoMapper.selectByPrimaryKey] - <== Row: 1, Mybatis从入门到精通, 刘增辉, 978-7-121-31797-1, 79.00, 电子工业出版社, 2018-11-02 23:00:43.0
[ex.book.mapper.BookInfoMapper.selectByPrimaryKey] - <== Total: 1
[book.BookMapperTest] - findById = BookInfo [id=1, bookName=Mybatis从入门到精通, bookAuthor=刘增辉, bookIsbn=978-7-121-31797-1, bookPrice=79.00, publishing=电子工业出版社, createTime=Fri Nov 02 23:00:43 CST 2018]
[ex.book.mapper.BookInfoMapper.selectByCondition] - ==> Preparing: select id, book_name, book_author, book_isbn, book_price, publishing, create_time from book_info WHERE book_isbn like ?
[ex.book.mapper.BookInfoMapper.selectByCondition] - ==> Parameters: %302%(String)
[ex.book.mapper.BookInfoMapper.selectByCondition] - <== Columns: id, book_name, book_author, book_isbn, book_price, publishing, create_time
[ex.book.mapper.BookInfoMapper.selectByCondition] - <== Row: 2, Java程序性能优化, 葛一鸣等, 978-7-302-29625-6, 59.20, 清华大学出版社, 2018-11-02 23:00:43.0
[ex.book.mapper.BookInfoMapper.selectByCondition] - <== Total: 1
[book.BookMapperTest] - selectByCondition = [BookInfo [id=2, bookName=Java程序性能优化, bookAuthor=葛一鸣等, bookIsbn=978-7-302-29625-6, bookPrice=59.20, publishing=清华大学出版社, createTime=Fri Nov 02 23:00:43 CST 2018]]
[org.springframework.context.support.GenericApplicationContext] - Closing org.springframework.context.support.GenericApplicationContext@13deb50e: startup date [Sat Nov 10 21:49:21 CST 2018]; root of context hierarchy
3、开发控制层(Controller层)
package ex.book.controller;
import java.util.List;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import ex.book.model.BookInfo;
import ex.book.service.BookService;
/**
* 图书CRUD控制层类
* @author huangqh
*
*/
@Controller
@RequestMapping("/manager")
public class BookController {
// 自动注入服务类
@Resource
private BookService bookService;
/**
* 查找所有图书
*/
@RequestMapping
public ModelAndView findAll(BookInfo bookInfo) {
// 创建视图
ModelAndView mv = new ModelAndView("books");
// 查询数据
List<BookInfo> bookInfos = bookService.selectByCondition(bookInfo);
// 视图绑定数据
mv.addObject("bookInfos", bookInfos);
// 返回视图
return mv;
}
/**
* 打开新增或修改的页面,使用get进行跳转
* @param id
* @return
*/
@RequestMapping(value="show", method=RequestMethod.GET)
public ModelAndView show(Long id) {
// 创建视图
ModelAndView mv = new ModelAndView("book_add");
// 图书bean
BookInfo bookInfo;
// 判断是新增还是修改
if (id == null) {// 新增
bookInfo = new BookInfo();// 返回一个空的对象
} else {// 更新
bookInfo = bookService.findById(id);// 根据id查询图书信息
}
// 绑定数据
mv.addObject("bookInfo", bookInfo);
// 返回结果
return mv;
}
/**
* 新增或修改的数据提交,使用post提交数据
* @param id
* @return
*/
@RequestMapping(value="saveOrUpdate", method=RequestMethod.POST)
public ModelAndView saveOrUpdate(@Valid BookInfo bookInfo, Errors error) {
// 创建空视图
ModelAndView mv = new ModelAndView();
// 检查是否有错
if (error.hasErrors()) {
// 取出所有的错误信息
List<FieldError> errors = error.getFieldErrors();
// 返回错误信息到页面
for (FieldError fieldError : errors) {
mv.addObject(fieldError.getField() + "Msg", fieldError.getDefaultMessage());
}
// 停留在原页面
mv.setViewName("book_add");
// 绑定数据
mv.addObject("bookInfo", bookInfo);
} else {
// 处理异常
try {
// 调用saveOrUpdate服务处理
bookService.saveOrUpdate(bookInfo);
// 成功后跳转到主页面
mv.setViewName("redirect:/manager");
} catch (Exception e) {// 出错后,显示错误信息
// 停留在原页面
mv.setViewName("book_add");
// 错误信息
mv.addObject("msg", e.getMessage());
// 绑定数据
mv.addObject("bookInfo", bookInfo);
}
}
// 返回结果
return mv;
}
/**
* 通过ID删除信息
* @param id
* @return
*/
@RequestMapping(value="delete", method=RequestMethod.POST)
@ResponseBody
public ModelMap delete(@RequestParam Long id) {
// 创建空返回map
ModelMap modelMap = new ModelMap();
// 处理
try {
boolean success = bookService.deleteById(id);
modelMap.put("success", success);
} catch (Exception e) {// 异常
modelMap.put("success", false);
modelMap.put("msg", e.getMessage());
}
// 返回结果
return modelMap;
}
}
4、开发视图层(View层)
books.jsp
<%@ page language="java" contentType="text/html; charset=UTF8"
pageEncoding="UTF8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<c:set var="path" value="${pageContext.request.contextPath}" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF8">
<script type="text/javascript" src="${path}/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="${path}/js/bootstrap.js"></script>
<script type="text/javascript" src="${path}/js/book.js"></script>
<title>图书信息</title>
</head>
<body>
<form:form modelAttribute="bookInfo" id="bookInfoForm" action="${path}/manager" method="post">
<table border="1" cellpadding="10" cellspacing="0" align="center">
<tr>
<th colspan="9">图书信息管理</th>
</tr>
<tr>
<td colspan="3" align="right">
<form:label path="bookName">书名:</form:label>
<form:input path="bookName" />
</td>
<td colspan="3" align="center">
<form:label path="bookAuthor">作者:</form:label>
<form:input path="bookAuthor" />
</td>
<td colspan="3" align="left">
<form:label path="bookIsbn">条码:</form:label>
<form:input path="bookIsbn" />
</td>
</tr>
<tr>
<td colspan="9" align="center">
<input type="submit" value="查询" />
<input type="button" onclick="resetForm()" value="重置" />
<input type="button" onclick="show()" value="添加" />
</td>
</tr>
<tr>
<th>图书编号</th>
<th>图书名称</th>
<th>作者</th>
<th>条形码</th>
<th>价格</th>
<th>出版社</th>
<th>创建时间</th>
<th>最后更新时间</th>
<th>操作</th>
</tr>
<c:forEach items="${bookInfos}" var="book">
<tr>
<td>${book.id}</td>
<td>${book.bookName}</td>
<td>${book.bookAuthor}</td>
<td>${book.bookIsbn}</td>
<td>${book.bookPrice}</td>
<td>${book.publishing}</td>
<td><fmt:formatDate value="${book.createTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td><fmt:formatDate value="${book.lastUpdatedTime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>[<a href="${path}/manager/show?id=${book.id}">修改</a>]
[<a href="javascript:;" onclick="deleteById('${book.id}', '${book.bookName}')">删除</a>]
</td>
</tr>
</c:forEach>
</table>
</form:form>
</body>
</html>
book_add.jsp
<?xml version="1.0" encoding="utf-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<c:set var="path" value="${pageContext.request.contextPath}" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="${path}/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="${path}/js/bootstrap.js"></script>
<script type="text/javascript" src="${path}/js/book.js"></script>
<title>图书维护</title>
</head>
<body>
<form:form modelAttribute="bookInfo" id="bookInfoEditForm" action="${path}/manager/saveOrUpdate" method="post">
<INPUT type="hidden" name="id" value="${bookInfo.id}"/>
<table border="1" cellpadding="10" cellspacing="0" align="center">
<c:if test="${msg != null}">
<tr>
<th colspan="2" style="color:red;max-width:400px;">${msg}</th>
</tr>
</c:if>
<tr>
<th colspan="2">图书维护</th>
</tr>
<tr>
<td><form:label path="bookName">书名:</form:label></td>
<td>
<form:input path="bookName" value="${bookInfo.bookName}"/>
<span id="nameMsg" style="color:red;">${bookNameMsg}</span>
</td>
</tr>
<tr>
<td><form:label path="bookAuthor">作者:</form:label></td>
<td>
<form:input path="bookAuthor" value="${bookInfo.bookAuthor}" />
<span id="authorMsg" style="color:red;">${bookAuthorMsg}</span>
</td>
</tr>
<tr>
<td><form:label path="bookIsbn">条形码:</form:label></td>
<td>
<form:input path="bookIsbn" value="${bookInfo.bookIsbn}" />
<span id="isbnMsg" style="color:red;">${bookIsbnMsg}</span>
</td>
</tr>
<tr>
<td><form:label path="bookPrice">价格:</form:label></td>
<td>
<form:input path="bookPrice" value="${bookInfo.bookPrice}" />
<span id="priceMsg" style="color:red;">${bookPriceMsg}</span>
</td>
</tr>
<tr>
<td><form:label path="publishing">出版社:</form:label></td>
<td>
<form:input path="publishing" value="${bookInfo.publishing}" />
<span id="publishingMsg" style="color:red;">${publishingMsg}</span>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" onclick="save()" value="保存" />
<input type="button" onclick="backToList()" value="取消" />
</td>
</tr>
</table>
</form:form>
</body>
</html>
// 保存功能
function save() {
// 验证表单通过后提交到后台
if (check()) {
// 验证通过后提交到后台
$("#bookInfoEditForm").submit();
}
}
// 弹出新增或修改页面
function show() {
window.location = '/book/manager/show';
}
// 表单重置
function resetForm() {
$("#bookInfoForm").find('input[type=text],select,input[type=hidden]').each(function() {
$(this).val('');
});
}
// 返回首页
function backToList() {
window.location = '/book/manager';
}
// 根据图书编号删除信息
function deleteById(id, name) {
var r = confirm('确定要删除【' + name + '】吗?');
if (r) {
$.ajax({
type : "POST",
url : "/book/manager/delete",
data : {
"id" : id
},
dataType : "json",
cache : false,
success : function(data) {
if (data.success) {
$("#bookInfoForm").submit();
} else {
alert('提示', data.msg);
}
},
error : function(error) {
alert('提示', error);
}
});
}
}
/**
* 表单验证
*
* @returns
*/
function check() {
// 书名不能为空
var bookName = $("#bookName").val();// 书名
if (bookName == null || bookName == '') {
$("#nameMsg").text("书名不能为空");
return false;
} else {
$("#nameMsg").text("");
}
// 作者不能为空
var bookAuthor = $("#bookAuthor").val();// 作者
if (bookAuthor == null || bookAuthor == '') {
$("#authorMsg").text("作者不能为空");
return false;
} else {
$("#authorMsg").text("");
}
// 条形码不能为空
var bookIsbn = $("#bookIsbn").val();// 条形码
if (bookIsbn == null || bookIsbn == '') {
$("#isbnMsg").text("条形码不能为空");
return false;
} else {
$("#isbnMsg").text("");
}
// 价格不能为空
var bookPrice = $("#bookPrice").val();// 价格
if (bookPrice == null || bookPrice == '') {
$("#priceMsg").text("价格不能为空");
return false;
} else {
var priceReg = /^\d{1,10}(\.\d{1,2})?$/;
if (!priceReg.test(bookPrice)) {
$("#priceMsg").text("价格格式错误");
return false;
} else {
$("#priceMsg").text("");
}
}
// 出版社不能为空
var publishing = $("#publishing").val();// 出版社
if (publishing == null || publishing == '') {
$("#publishingMsg").text("出版社不能为空");
return false;
} else {
$("#publishingMsg").text("");
}
// 验证通过
return true;
}
5、功能已开发完毕,请看下一节项目打包部署。项目DEMO下载地址或百度网盘