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数据库操作汇总
1 关于orm orm即object relational mapping,对象关系映射,即将数据库中的表映射成对象. 常用的orm有以下: mybatis spring jdbc template ...
- 195. Spring Boot 2.0数据库迁移:Flyway
[视频&交流平台] àSpringBoot视频:http://t.cn/R3QepWG à SpringCloud视频:http://t.cn/R3QeRZc à Spring Boot源码: ...
- spring boot之从零开始开发自己的网站
概述 首先要感谢两位大神,该项目的想法来源自tale和MyBlog,本项目的想法. 做了一些改造,增加了一些功能和一些代码的重构,并且更换了博客主题. 关于项目,对于开发的练手项目,能够工程化,严谨一 ...
- Spring Boot 知识图谱
最近有意重新学习下SpringBoot知识,特地总结了SpringBoot的知识点,对于想要学习的人来说,够用. SpringBoot学习路径 第一部分:了解 Spring Boot Spring B ...
- 国内最全的Spring Boot系列之二
历史文章 <国内最全的Spring Boot系列之一> 视频&交流平台 SpringBoot视频:http://t.cn/R3QepWG Spring Cloud视频:http:/ ...
- 200. Spring Boot JNDI:在Tomcat中怎么玩JNDI?
[视频&交流平台] àSpringBoot视频:http://t.cn/R3QepWG à SpringCloud视频:http://t.cn/R3QeRZc à Spring Boot源 ...
- 最全spring boot视频系列,你值得拥有
================================== 从零开始学Spring Boot视频 ================================== àSpringBoot ...
- 1.spring boot起步之Hello World【从零开始学Spring Boot】
[视频&交流平台] àSpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008&utm ...
- 0. 前言【从零开始学Spring Boot】
[视频&交流平台] àSpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008&utm ...
随机推荐
- Docker简介与安装配置
目录 Docker简介 什么是Docker 为啥要用容器 Docker Engine Docker架构说明 Docker安装 Docker版本介绍 Ubuntu安装docker-ce CentOS7安 ...
- OpenLDAP介绍和安装
LADP 1.目录服务 目录是一个为查询.浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样.目录数据库和关系数据库不同,它有优异的读性能,但写性 ...
- 第10章-Vue.js 项目实战
一.本节内容 掌握项目环境中路由的配置方法 ***** 熟练掌握编写单文件组件的编写 *** 能够使用swiper.js进行轮播图组件的封装 能够使用axios进行数据请求 二.webpack项目的目 ...
- MySQL搭建环境
一.MySQL安装 Windows下安装参考网址:https://blog.csdn.net/NepalTrip/article/details/79492058 Ubuntu Linux下安装参考网 ...
- python---web微信开发
一:轮询,长轮询,WebSocket了解 轮询: 在前端,设置时间内,一直向后端发送请求.例如:使用setInterval方法设置定时器,一秒向后端发送一次请求,去主动获取数据,进行更新由于前端一直请 ...
- codevs 1540 1540 银河英雄传说
1540 银河英雄传说 题目描述 Description 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银 ...
- ssh 批量执行命令
# python3.5 + paramiko # pip 是python的包管理工具,在shell里执行如下命令安装paramoko模块 # pip install paramiko # import ...
- <转>Android APP字体大小,不随系统的字体大小变化而变化的方法
从android4.0起系统设置的”显示“提供设置字体大小的选项.这个设置直接会影响到所有sp为单位的字体适配,所以很多app在设置了系统字体后瞬间变得面目全非.下面是解决方案 Resources r ...
- django错误笔记——URL
django提交表单提示"RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and ...
- xampp + windows 配置 memcache流程
1.运行xampp服务,打开phpinfo查看信息,如下图: 从上到下,依次为 PHP版本:5.6: architecture:x86: TS:线程安全: vc11 2.牢记以上几个横线内容之后去下载 ...