Spring Boot数据库交互
Posted 杰克思勒(Jacksile)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot数据库交互相关的知识,希望对你有一定的参考价值。
在上篇文件的基础上进行开发,简单实现一下增、查操作,删除和修改类似,作为一个demo就暂时不做重复工作了,实现原理类似
IDEA创建Spring Boot项目
项目结构
新建mysql数据库相关信息
-- 建数据库 create database if not exists test; -- 建表 CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `password` varchar(30) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name_UNIQUE` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
maven中增加配置四个架包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.35</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 非常重要,缺少这个架包,会导致html无法正常解析,会产生Whitelabel Error Page错误,并且控制层传值无法正常获取--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
配置文件 application.properties
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=true&allowMultiQueries=true&serverTimezone=Asia/Hong_Kong spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.tomcat.max-wait=10000 spring.datasource.tomcat.max-active=50 spring.datasource.tomcat.test-on-borrow=true spring.datasource.testWhileIdle = true spring.datasource.timeBetweenEvictionRunsMillis = 60000 # 暂时用不到 spring.mvc.view.prefix=/templates/ # 暂时用不到 spring.mvc.view.suffix=.html
建立实体类 User.java
package com.springboot.demo.domain; import javax.persistence.*; @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String password; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
建立持久层接口 UserDao.java
package com.springboot.demo.dao; import com.springboot.demo.domain.User; import java.util.List; public interface UserDao { /** * 插入一个用户 * @param user * @return */ Long insertUser(User user); /** * 通过用户名获取用户,用户名唯一 * @param name * @return */ User getUserByName(String name); /** * 列出所有的用户信息 * @return */ List<User> getAllUsers(); /** * 删除暂不实现 * @param user */ void delete(User user); /** * 修改暂不实现 * @param user */ void update(User user); }
实现持久层接口 UserRepository.java
package com.springboot.demo.domain; import com.springboot.demo.dao.UserDao; import com.springboot.demo.utils.RowMapperFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; import java.util.HashMap; import java.util.List; import java.util.Map; @Repository public class UserRepository implements UserDao { @Autowired private NamedParameterJdbcTemplate jdbcTemplate; @Override public User getUserByName(String name) { String sql = "select * from User user where name=:name"; Map<String, Object> param = new HashMap<>(); param.put("name", name); return jdbcTemplate.queryForObject(sql, param, RowMapperFactory.getInstance(User.class)); } @Override public Long insertUser(User user) { String sql = "insert into user(name, password) values(:name, :password)"; Map<String, Object> param = new HashMap<>(); param.put("name", user.getName()); param.put("password", user.getPassword()); return (long) jdbcTemplate.update(sql, param); } @Override public List<User> getAllUsers() { String sql = "select * from User user"; Map<String, Object> param = new HashMap<>(); return jdbcTemplate.query(sql, param, RowMapperFactory.getInstance(User.class)); } @Override public void delete(User user) { } @Override public void update(User user) { } }
建立服务层类 UserService.java
package com.springboot.demo.service; import com.springboot.demo.dao.UserDao; import com.springboot.demo.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; @Service public class UserService { @Autowired private UserDao userDao; /** * 通过用户名获取用户,用户名唯一 * @param name * @return */ public User getUserByName(String name) { return userDao.getUserByName(name); } /** * 插入一个用户 * @param user * @return */ public Long insertUser(User user) { User userDb = getUserByName(user.getName()); if(Objects.isNull(userDb)) return userDao.insertUser(user); else return userDb.getId(); } /** * 列出所有的用户信息 * @return */ public List<User> getAllUsers() { return userDao.getAllUsers(); } }
建立控制层类 LoginController.java
package com.springboot.demo.web; import com.springboot.demo.domain.User; import com.springboot.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; import java.util.Objects; @Controller @RequestMapping("/admin") public class LoginController { @Autowired private UserService userService; @RequestMapping(value="/userInfo") public String userInfo(Model model) { String managerName = "Jef"; User userDb = userService.getUserByName(managerName); if(Objects.isNull(userDb)) { userDb = new User(); userDb.setName(managerName); userDb.setPassword("123"); userService.insertUser(userDb); } model.addAttribute("manager", managerName); List<User> users = userService.getAllUsers(); model.addAttribute("users", users); return "index"; } }
工具类 RowMapperFactory.java
package com.springboot.demo.utils; import org.springframework.jdbc.core.RowMapper; import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; public class RowMapperFactory { public static <K> RowMapper<K> getInstance(Class<K> clazz) { return getRowMapper(clazz); } public static <K> RowMapper<K> getRowMapper(Class<K> clazz) { return new RowMapper<K>() { private AutoRowMapper<K> rm = new AutoRowMapper(clazz); @Override public K mapRow(ResultSet rs, int rowNum) throws SQLException { try { return rm.mapRow(rs, rowNum, clazz.newInstance()); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); return null; } } }; } /** * 这是一个用于简化 rowMapper 的编写辅助类。 * <p/> * 本类会自动跳过 entity 中存在,但是在查询语句中不存在的列。 * * @param <T> entity type */ private static class AutoRowMapper<T> { private Map<String, String> colName2SetterMap = new HashMap<>(); // 数据列名到 setter 名称的映射 private Map<String, Method> setterMap = new HashMap<>(); // setter 名称到 setter 方法的映射 private Map<String, String> setterParamMap = new HashMap<>(); // setter 名称到 setter 参数类型的映射 /** * 初始化 * * @param t 实体类的类对象 */ protected <T> AutoRowMapper(Class<T> t) { Method[] ms = t.getMethods(); for (int i = 0; i < ms.length; i++) { String name = ms[i].getName(); if (name.startsWith("set") && ms[i].getParameterCount() == 1) { setterMap.put(name, ms[i]); setterParamMap.put(name, ms[i].getGenericParameterTypes()[0].getTypeName()); colName2SetterMap.put(setterToColName(name), name); } } } /** * 在子类中,要实现的 RowMapper.mapRow 中掉用此方法。 * * @param rs 结果集 * @param rowNum 结果集行号 * @param t entity 对象,用于装填查询结果行数据 * @return 传入的 entity 对象 */ public T mapRow(ResultSet rs, int rowNum, T t) { for (String col : colName2SetterMap.keySet()) { try { int index = rs.findColumn(col); // 如果找不到列,就会抛出异常 String setterName = colName2SetterMap.get(col); inject(setterMap.get(setterName), setterParamMap.get(setterName), rs, index, t); } catch (SQLException ex) { continue; } } return t; } /** * 把 setter 名称转换为列名。如 setCreatedOn --> created_on */ private static String setterToColName(String setterName) { String property = setterName.substring(3, setterName.length()); StringBuilder sb = new StringBuilder().append(property.charAt(0)); for(int i = 1; i < property.length(); i++) { char c = property.charAt(i); if(Character.isUpperCase(c)) { sb.append(""); } sb.append(c); } return sb.toString().toLowerCase(); } /** * 把指定列按类型注入 entity. * <p/> * 目前支持的类字段类型有: * <pre> * java.lang.Boolean boolean * java.lang.Byte byte * java.lang.Long long * java.lang.Integer int * java.lang.Short short * java.lang.Float float * java.lang.Double double * java.lang.Date * java.lang.String * java.sql.Blob * java.math.BigDecimal * </pre> */ private void inject(Method getter, String fieldType, ResultSet rs, int index, T t) { try { switch (fieldType) { case "java.lang.Boolean": // 布尔值 case "boolean": getter.invoke(t, rs.getBoolean(index)); break; case "java.lang.Byte": // 字节 case "byte": getter.invoke(t, rs.getByte(index)); break; case "java.lang.Long": // Long case "long": getter.invoke(t, rs.getLong(index)); break; case "java.lang.Integer": // Int case "int": getter.invoke(t, rs.getInt(index)); break; case "java.lang.Short": // Short case "short": getter.invoke(t, rs.getShort(index)); break; case "java.lang.Float": // Float case "float": getter.invoke(t, rs.getFloat(index)); break; case "java.lang.Double": // Double case "double": getter.invoke(t, rs.getDouble(index)); break; case "java.lang.Date": getter.invoke(t, rs.getDate(index)); break; case "java.lang.String": getter.invoke(t, rs.getString(index)); break; case "java.sql.Blob": getter.invoke(t, rs.getBlob(index)); break; case "java.math.BigDecimal": getter.invoke(t, rs.getBigDecimal(index)); break; default: getter.invoke(t, rs.getObject(index)); break; } } catch (Exception ex) { ex.printStackTrace(); } } } }
页面展示文件 index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html"> <title>Spring Boot User</title> <link rel="stylesheet" type="text/css" media="all" href="/css/bootstrap.min.css"> </head> <body> <!-- Thymeleaf 常用属性进行取值 --> <h1>取控制层传过来的值</h1> <h1>Manager = </h1> <td class="text" th:text="${manager}" ></td> <h1>测试JS是否有效</h1> <p id="testId"></p> <h1>把所有用户信息列出来</h1> <ul class="timeline"> <div th:each="entry, status : ${users}"> <li th:attr="class=${status.odd} ? \'timeline-inverted\' : \'\'"> <div class="tl-circ"></div> <div class="timeline-panel"> <div class="tl-heading"> <h4><span th:text="${entry.name}">TITLE</span></h4> </div> </div> </li> </div> </ul> <script src="/js/jquery-3.1.1.js"></script> <script> $(document).ready(function () { $( "#testId" ).text( "Test Id" ); }); </script> </body> </html>
其中css、js文件,拷贝文件名去搜索可以直接进入他们的官网下载
启动Spring Boot项目的类 DemoApplication.java
package com.springboot.demo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration @SpringBootApplication // 自动扫描下面配置的包 @ComponentScan({"com.springboot.demo"}) public class DemoApplication { private static final Logger log = LoggerFactory.getLogger(DemoApplication.class); public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
运行结果
http://localhost:8080/admin/userInfo
以上是关于Spring Boot数据库交互的主要内容,如果未能解决你的问题,请参考以下文章
spring boot + hibernate 如何实现前后端交互的。如果前台提交一个表单进行保存
Spring Boot数据库交互之Spring Data JPA
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式