相关pom依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
application.yml配置
spring: jpa: hibernate: ddl-auto: update show-sql: true
自动建表相关代码
package com.lingerqi.springboot03.entity; import lombok.Data; import javax.persistence.*; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-11-30 16:42 */ @Data @Entity @Table(name = "t_springboot_book_1") public class Book { @Id @GeneratedValue private Integer bid; @Column(length = 100) private String bname; @Column private float price; }
jpa值增删改查
* 只要继承JpaRepository,通常所用的增删查改方法都有
* 第一个参数:操作的实体类
* 第二个参数:实体类对应数据表的主键
*/
public interface JpaDao extends JpaRepository<Book, Integer> { }
controller层
@Autowired private JpaDao jpaDao; @RequestMapping("/add") public String add(Book book){ jpaDao.save(book); return "success"; } @RequestMapping("/edit") public String edit(Book book){ jpaDao.save(book); return "success"; } @RequestMapping("/del") public String del(Book book){ jpaDao.delete(book); return "success"; } @RequestMapping("/getOne") public Book getOne(Integer bid){ // 会出现懒加载问题:org.hibernate.LazyInitializationException: could not initialize proxy - no Session // return jpaDao.getOne(bid); return jpaDao.findById(bid).get(); } @RequestMapping("/getAll") public List<Book> getAll(){ return jpaDao.findAll(); }
新增:
jpa值复杂查询
* 要使用高级查询必须继承 * org.springframework.data.jpa.repository.JpaSpecificationExecutor<T>接口 */ public interface JpaDao extends JpaRepository<Book, Integer>, JpaSpecificationExecutor<Book> { }
controller层
@RequestMapping("/getCondition") public List<Book> getCondition(Book book){ return jpaDao.findAll(new Specification<Book>() { @Override public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate predicate = criteriaBuilder.conjunction(); if(book != null){ if(null != book.getBname() && !"".equals(book.getBname())){ predicate.getExpressions().add(criteriaBuilder.like(root.get("bname"),"%"+book.getBname()+"%")); } } return predicate; } }); }
SpringBoot+bootstarp界面版增删改查及图片上传
pom:
<mysql.version>5.1.44</mysql.version> <version>${mysql.version}</version> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>
application.yml文件配置
server: port: 80 servlet: context-path: / spring: jpa: hibernate: ddl-auto: update show-sql: true datasource: #1.JDBC type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC username: root password: 123 druid: initial-size: 5 min-idle: 5 max-active: 20 max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 30000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: true test-on-return: false pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 filter: stat: merge-sql: true slow-sql-millis: 5000 web-stat-filter: enabled: true url-pattern: /* exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" session-stat-enable: true session-stat-max-count: 100 stat-view-servlet: enabled: true url-pattern: /druid/* reset-enable: true login-username: root login-password: 123 allow: 127.0.0.1 #deny: 192.168.1.100 thymeleaf: cache: false # 解决图片上传大小限制问题,也可采取配置类 servlet: multipart: max-file-size: 20MB max-request-size: 60MB
Springbootapplication.java:
@EnableTransactionManagement @SpringBootApplication
上传文件映射配置类MyWebAppConfigurer.java
package com.lingerqi.springboot03.config; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-12-01 11:10 */ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * 资源映射路径 */ @Configuration public class MyWebAppConfigurer extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/uploadImages/**").addResourceLocations("file:E:/temp/"); super.addResourceHandlers(registry); } }
后台代码
StringUtils
package com.lingerqi.springboot03.utils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; public class StringUtils { // 私有的构造方法,保护此类不能在外部实例化 private StringUtils() { } /** * 如果字符串等于null或去空格后等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isBlank(String s) { boolean b = false; if (null == s || s.trim().equals("")) { b = true; } return b; } /** * 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false * * @param s * @return */ public static boolean isNotBlank(String s) { return !isBlank(s); } /** * set集合转string * @param hasPerms * @return */ public static String SetToString(Set hasPerms){ return Arrays.toString(hasPerms.toArray()).replaceAll(" ", "").replace("[", "").replace("]", ""); } /** * 转换成模糊查询所需参数 * @param before * @return */ public static String toLikeStr(String before){ return isBlank(before) ? null : "%"+before+"%"; } /** * 将图片的服务器访问地址转换为真实存放地址 * @param imgpath 图片访问地址(http://localhost:8080/uploadImage/2019/01/26/20190126000000.jpg) * @param serverDir uploadImage * @param realDir E:/temp/ * @return */ public static String serverPath2realPath(String imgpath, String serverDir, String realDir) { imgpath = imgpath.substring(imgpath.indexOf(serverDir)); return imgpath.replace(serverDir,realDir); } /** * 过滤掉集合里的空格 * @param list * @return */ public static List<String> filterWhite(List<String> list){ List<String> resultList=new ArrayList<String>(); for(String l:list){ if(isNotBlank(l)){ resultList.add(l); } } return resultList; } /** * 从html中提取纯文本 * @param strHtml * @return */ public static String html2Text(String strHtml) { String txtcontent = strHtml.replaceAll("</?[^>]+>", ""); //剔出<html>的标签 txtcontent = txtcontent.replaceAll("<a>\\s*|\t|\r|\n</a>", "");//去除字符串中的空格,回车,换行符,制表符 return txtcontent; } public static void main(String[] args) { } }
PageUtil
package com.lingerqi.springboot03.utils; import java.util.Map; import java.util.Set; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-12-01 11:10 * * 基于bootstrap3生成分页代码 */ public class PageUtil { public static String createPageCode(PageBean pageBean) { StringBuffer sb = new StringBuffer(); /* * 拼接向后台提交数据的form表单 * 注意:拼接的form表单中的page参数是变化的,所以不需要保留上一次请求的值 */ sb.append("<form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>"); sb.append("<input type='hidden' name='page'>"); Map<String, String[]> parameterMap = pageBean.getParamMap(); if(parameterMap != null && parameterMap.size() > 0) { Set<Map.Entry<String, String[]>> entrySet = parameterMap.entrySet(); for (Map.Entry<String, String[]> entry : entrySet) { if(!"page".equals(entry.getKey())) { String[] values = entry.getValue(); for (String val : values) { sb.append("<input type='hidden' name='"+entry.getKey()+"' value='"+val+"'>"); } } } } sb.append("</form>"); if(pageBean.getTotal()==0){ return "未查询到数据"; }else{ sb.append("<li><a href='javascript:gotoPage(1)'>首页</a></li>"); if(pageBean.getPage()>1){ sb.append("<li><a href='javascript:gotoPage("+pageBean.getPreviousPage()+")'>上一页</a></li>"); }else{ sb.append("<li class='disabled'><a href='javascript:gotoPage(1)'>上一页</a></li>"); } for(int i=pageBean.getPage()-1;i<=pageBean.getPage()+1;i++){ if(i<1||i>pageBean.getMaxPage()){ continue; } if(i==pageBean.getPage()){ sb.append("<li class='active'><a href='#'>"+i+"</a></li>"); }else{ sb.append("<li><a href='javascript:gotoPage("+i+")'>"+i+"</a></li>"); } } if(pageBean.getPage()<pageBean.getMaxPage()){ sb.append("<li><a href='javascript:gotoPage("+pageBean.getNextPage()+")'>下一页</a></li>"); }else{ sb.append("<li class='disabled'><a href='javascript:gotoPage("+pageBean.getMaxPage()+")'>下一页</a></li>"); } sb.append("<li><a href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a></li>"); } /* * 给分页条添加与后台交互的js代码 */ sb.append("<script type='text/javascript'>"); sb.append(" function gotoPage(page) {"); sb.append(" document.getElementById('pageBeanForm').page.value = page;"); sb.append(" document.getElementById('pageBeanForm').submit();"); sb.append(" }"); sb.append(" function skipPage() {"); sb.append(" var page = document.getElementById('skipPage').value;"); sb.append(" if(!page || isNaN(page) || parseInt(page)<1 || parseInt(page)>"+pageBean.getMaxPage()+"){"); sb.append(" alert('请输入1~N的数字');"); sb.append(" return;"); sb.append(" }"); sb.append(" gotoPage(page);"); sb.append(" }"); sb.append("</script>"); return sb.toString(); } }
dao层
package com.lingerqi.springboot03.repository; import com.lingerqi.springboot03.entity.Teacher; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-11-30 16:42 * * 只要继承JpaRepository,通常所用的增删查改方法都有 * 第一个参数:操作的实体类 * 第二个参数:实体类对应数据表的主键 * * 要使用高级查询必须继承 * org.springframework.data.jpa.repository.JpaSpecificationExecutor<T>接口 */ public interface TeacherDao extends JpaRepository<Teacher, Integer>, JpaSpecificationExecutor<Teacher> { }
controler层
package com.lingerqi.springboot03.controller; import com.lingerqi.springboot03.entity.Teacher; import com.lingerqi.springboot03.service.TeacherService; import com.lingerqi.springboot03.utils.PageBean; import com.lingerqi.springboot03.utils.PageUtil; import com.lingerqi.springboot03.utils.StringUtils; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; /** * @author xyls * @blog name & blog address 027@0030 * @create 2019-12-01 11:57 */ @Controller @RequestMapping("/teacher") public class TeacherController { @Autowired private TeacherService teacherService; @RequestMapping("/listPager") public ModelAndView list(Teacher teacher, HttpServletRequest request) { PageBean pageBean = new PageBean(); pageBean.setRequest(request); ModelAndView modelAndView = new ModelAndView(); Page<Teacher> teachers = teacherService.listPager(teacher, pageBean); modelAndView.addObject("teachers", teachers.getContent()); pageBean.setTotal(teachers.getTotalElements() + ""); modelAndView.addObject("pageCode", PageUtil.createPageCode(pageBean)/*.replaceAll("<","<").replaceAll(">:",">")*/); modelAndView.setViewName("list"); return modelAndView; } @RequestMapping("/toEdit") public ModelAndView toEdit(Teacher teacher) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("edit"); modelAndView.addObject("sexArr", new String[]{"男", "女"}); if (!(teacher.getTid() == null || "".equals(teacher.getTid()))) { Teacher t = teacherService.findById(teacher.getTid()); modelAndView.addObject("teacher", t); } return modelAndView; } @RequestMapping("/add") public String add(Teacher teacher, MultipartFile image) { try { String diskPath = "E://temp/" + image.getOriginalFilename(); String serverPath = "/uploadImages/" + image.getOriginalFilename(); if (StringUtils.isNotBlank(image.getOriginalFilename())) { FileUtils.copyInputStreamToFile(image.getInputStream(), new File(diskPath)); teacher.setImagePath(serverPath); } teacherService.save(teacher); } catch (IOException e) { e.printStackTrace(); } return "redirect:/teacher/listPager"; } @RequestMapping("/edit") public String edit(Teacher teacher, MultipartFile image) { String diskPath = "E://temp/" + image.getOriginalFilename(); String serverPath = "/uploadImages/" + image.getOriginalFilename(); if (StringUtils.isNotBlank(image.getOriginalFilename())) { try { FileUtils.copyInputStreamToFile(image.getInputStream(), new File(diskPath)); teacher.setImagePath(serverPath); } catch (IOException e) { e.printStackTrace(); } } teacherService.save(teacher); return "redirect:/teacher/listPager"; } @RequestMapping("/del/{bid}") public String del(@PathVariable(value = "bid") Integer bid) { teacherService.deleteById(bid); return "redirect:/teacher/listPager"; } }
页面层
list.html
<!DOCTYPE html> <html lang="en"> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>书籍列表</title> <script type="text/javascript" th:src="@{/static/js/xxx.js}"></script> <link rel="stylesheet" th:href="@{/static/js/bootstrap3/css/bootstrap.min.css}"> <link rel="stylesheet" th:href="@{/static/js/bootstrap3/css/bootstrap-theme.min.css}"> <script type="text/javascript" th:src="@{/static/js/bootstrap3/js/jquery-1.11.2.min.js}"></script> <script type="text/javascript" th:src="@{/static/js/bootstrap3/js/bootstrap.min.js}"></script> </head> <body> <form th:action="@{/teacher/listPager}" method="post"> 书籍名称: <input type="text" name="tname" /> <input type="submit" value="提交"/> </form> <a th:href="@{/teacher/toEdit}">新增</a> <table border="1px" width="600px"> <thead> <tr> <td>ID</td> <td>头像</td> <td>姓名</td> <td>性别</td> <td>简介</td> <td>操作</td> </tr> </thead> <tbody> <tr th:each="teacher : ${teachers}"> <td th:text="${teacher.tid}"></td> <td><img style="width: 60px;height: 60px;" id="imgshow" th:src="${teacher.imagePath}" th:alt="${teacher.tname}"/></td> <!--<td th:text="${teacher.imagePath}"></td>--> <td th:text="${teacher.tname}"></td> <td th:text="${teacher.sex}"></td> <td th:text="${teacher.description}"></td> <td> <a th:href="@{'/teacher/del/'+${teacher.tid}}">删除</a> <a th:href="@{'/teacher/toEdit?tid='+${teacher.tid}}">修改</a> </td> </tr> </tbody> </table> <nav> <ul class="pagination pagination-sm" th:utext="${pageCode}"> </ul> <!--<ul class="pagination pagination-sm">--> <!--<form id='pageBeanForm' action='http://localhost:8080/springboot/teacher/listPager' method='post'><input type='hidden' name='page'></form>--> <!--<li><a href='javascript:gotoPage(1)'>首页</a></li>--> <!--<li class='disabled'><a href='javascript:gotoPage(1)'>上一页</a></li>--> <!--<li class='active'><a href='#'>1</a></li>--> <!--<li><a href='javascript:gotoPage(2)'>2</a></li>--> <!--<li><a href='javascript:gotoPage(2)'>下一页</a></li>--> <!--<li><a href='javascript:gotoPage(4)'>尾页</a></li>--> <!--<script type='text/javascript'> function gotoPage(page) { document.getElementById('pageBeanForm').page.value = page; document.getElementById('pageBeanForm').submit(); } function skipPage() { var page = document.getElementById('skipPage').value; if(!page || isNaN(page) || parseInt(page)<1 || parseInt(page)>4){ alert('请输入1~N的数字'); return; } gotoPage(page); }</script>--> <!--</ul>--> </nav> </body> </html>
edit.html:
<!DOCTYPE html> <html lang="en"> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>用户编辑界面</title> <script type="text/javascript"> function preShow() { } </script> </head> <body> <form th:action="@{${teacher.tid} ? '/teacher/edit' : '/teacher/add'}" method="post" enctype="multipart/form-data"> <input type="hidden" name="tid" th:value="${teacher.tid}" /> <input type="hidden" name="imagePath" th:value="${teacher.imagePath}" /> <img id="imgshow" src="" alt=""/> <input type="file" name="image" onchange="preShow();"></br> 教员名称: <input type="text" name="tname" th:value="${teacher.tname}" /></br> 教员描述: <input type="text" name="description" th:value="${teacher.description}" /></br> 单选回显 <input type="radio" name="sex" th:each ="s:${sexArr}" th:value="${s}" th:text ="${s}" th:attr ="checked=${s == teacher.sex}"> <input type="submit" value="提交"/> </form> </body> </html>
案例结果截图