关于Springboot开发接着来,前面只是大概怎么运行Springboot框架,没有任何操作,啥事不干的代码是没有意义的。我们从最基本的来说起。数据库怎么操作,增加,修改、删除和查询。
首先项目要能运行,不仅得有jdk,有maven,还得有数据库。因为本文是讲解springboot如何操作数据库嘛。这里用到的数据库是sqlserver2008,其连接方式在resources 目录下 application.properties 配置文件中,如下。
#springboot 服务启动时所打开的端口号
server.port=8181
#数据库地址以及数据库名 127.0.0.1--数据库IP our_herb数据库名称
spring.datasource.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=yourdatabase
#访问数据库用户名
spring.datasource.username=sa
#访问数据库密码
spring.datasource.password=sa
#方言的写法与数据库版本有关系哦
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
#mysql写法有点类似
#spring.datasource.jdbc-url=jdbc:mysql://127.0.0.1:3306/yourdatabase
#spring.datasource.username=root
#spring.datasource.password=root
#spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
这个配置文件还是比较好懂的,配置文件就放这个路径下。这个路径也可以换,但是不要换 ,别给自己找麻烦。这里也不说为什么了。网上学习Springboot操作数据库大多用mysql来演示。其实Sqlserver入门学习会更方便一点点。安装个Sqlserver,这个事情相信难不倒大家。再说一句,Sqlserver其实也是有一个免费版本的,还有,如果换别的数据库,Oracle,Mysql之类的,改一下配置文件即可,代码都不带改的,Springboot都帮你做了。当然,pom.xml得修改一下,具体怎么修改,后面再说。
Springboot代码运行前,在数据库里建一个表, t_test_data 否则后面的查询、增加和删除功能就没法运行了。建表后,如果还想加个主键或者索引什么的,随便你了。这个不是不重要,只是这里不是重点而已。
CREATE TABLE [t_test_data](
[id] [varchar](50) NULL,
[name] [varchar](50) NULL,
[gdate] [datetime] NULL,
[gdata] [float] NULL)
代码下载后,导入eclipse,看看整体结构,大概如下:
重点是左边画红框的,这个目录结构几乎是所有项目的通用结构,哪个目录下放哪些文件,有点顾名思义的感觉。comm 下是一些公共类,比如工具类。config下是配置类,Controller下是Controller类,entity下是实体类,repository是直接访问数据库的类,service下是service类。
所有的静态资源,包括html,css,js文件,都是放在resources/static下。如果文件有很多,就分门别类再往下建子目录。
什么样的文件放哪个目录,不可以随随便便。文件放哪里,这只是一个约定俗成的做法,虽然有些并不是强制要求。但是,不遵守默认规则的后果,往往是一件简单的事情浪费很多的时间。或者时不时犯点低级错误。正如生活中的一些潜规则,还是尽量遵守的好。
Springboot操作数据库,同样是先启动服务。右键 SringbootApplication 文件,Debug As ---> Java Application,服务器起来后,在浏览器中敲入,http://localhost:8181/webapp/Query.html ,这个8181就可以在上面配置中 server.port=8181 处随便修改,是不是很简单了。好了,看看页面效果。
怎么样?高手看来,啥也不是。但是作为一个初学者,这个页面能出来也很不错,走通了第一步嘛。估计各位初学者在出来这个页面之前,会遇到各种各样的问题........
也许你的页面,除了增加按钮和标题,剩下一片空白,那是因为没有数据。点几下”增加“按钮,就应该就有数据了。在这个页面点增加,页面就会多一条数据,点删除就少一条。
到这里,程序完全运行起来了。路走通了,剩下的事情就是看代码,理解和消化好这个过程,把这支撑这个页面运行的前后台代码给看明白了。Springboot数据库操作就算是会了。就可以某公司干活了,就开始挣高薪了,然后迎娶白富美......无论什么时候,梦想一定要有。
通过浏览器发请求的页面Query.html,这就是所谓的个静态页面,css,javascript,html代码都有点。静态页面不管是css还是javascript语法都相对没那么严格。大概看看吧
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XX实时数据查询</title>
<style type="text/css">
body{font-size:12px;text-align:center;margin:0;padding:0;}
table {margin:1px 1px 0px 0px;}
.table {
width:100%;
border: 1px solid #ddd;
border-collapse: collapse;
}
.table thead tr th,
.table tbody tr td {
padding: 6px 6px;
text-align: center;
color: #333;
border: 1px solid #000;
border-collapse: collapse;
}
</style>
<!--引用 jquery 组件 -->
<script type="text/javascript" src="js/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
//页面初始化执行。所以每次刷新页面都重新查询
$(function () {
Query();
});
//查询数据
function Query(){
$.getJSON("user/findall", function (o) { LoadTable(o); });
};
function LoadTable(data){
$("#J_TbData").empty();
for( var i = 0; i < data.length; i++ ) {
//动态创建一个tr行标签,并且转换成jQuery对象
var $trTemp = $("<tr></tr>");
var bgcolor = (i%2==0) ? "#fff":"#eee"; //隔行变色效果
//往行里面追加 td单元格
$trTemp.append("<td>"+ (i + 1) +"</td>");
$trTemp.append("<td>"+ data[i]["id"] +"</td>");
$trTemp.append("<td>"+ data[i]["name"] +"</td>");
$trTemp.append("<td>"+ data[i]["gdate"] +"</td>");
$trTemp.append("<td>"+ data[i]["gdata"] +"</td>");
$trTemp.append("<td><a href=# onclick=del('"+ data[i]["id"] + "')>删除</a></td>");
$trTemp.css({"background": bgcolor});
$trTemp.appendTo("#J_TbData");
}
};
//删除数据
function del(id){
//删除前提示一下,正常业务应该有
if(!confirm("删除了无法恢复?")){
return;
};
var url = "user/remove?id=" + id;
$.getJSON(url, function (p) {
if (!p.success) {
alert(p.msg);
return;
};
Query();
});
};
//增加数据
function add(){
var url = "user/add?name=abc";
$.getJSON(url, function (o) {
$("#msg").html(JSON.stringify(o));
Query();
});
};
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
};
</script>
</head>
<body>
<div id="container" style="margin: 0 auto;font-size:20px;">XX实时数据查询
<input type="button" value="增加" name="w4" onclick="add()"/>
<div id="msg" style="color:blue"></div>
</div>
<table id="process" class="table" cellspacing="0" cellpadding="0">
<thead>
<tr style="background-color:#ccc;">
<th>序号</th>
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>数据</th>
<th>.</th>
</tr>
</thead>
<tbody id="J_TbData">
</tbody>
</table>
</body>
</html>
这个代码虽然有100多行,其实就是html页面,引用JQuery调用后台java提供方法来读取数据。即便是你一点都看不懂,也不用着急,慢慢来,多看两眼,自然会明白的。当年的我也是一点都看不懂哦,何况现在还有强大的互联网支撑你哦。
其中 $.getJSON就是JQueryj向后台请求数据一个方法,这个东西就是干这个的,不用什么特殊的理解,对于初学者更没必要看什么JQuery源码了。
UserController是后台java代码对外提供数据类。没有特殊处理的话,Controller 中的方法是可以通过浏览器直接访问的。试一下这个路径就明白了。http://localhost:8181/webapp/user/findall
package com.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.springboot.service.UserService;
import com.springboot.entity.MJson;
import com.springboot.entity.sqlserver.User;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/findall")
public List<User> findAll() {
return userService.findAll();
}
@RequestMapping("/remove")
public MJson remove(@RequestParam(value = "id") String id) {
return userService.remove(id);
}
@RequestMapping("/add")
public MJson add(@RequestParam(value = "name") String name) {
//随机数,只是测试,真实场景可能各种来源
float gdata = (float)(Math.random()*99+ 1);
return userService.add(name, gdata);
}
}
Controller这一层,主要是为前台页面服务,比如转json格式啊,处理日期格式,处理数字格式,参数为空判断,屏蔽页面不需要的字段之类的。总之,大都是一些比较简单逻辑代码。当然,如果非要在一层写很多的,复杂的业务逻辑处理代码,也是可以的。事实上,也确实有很多人是比较随意的。这个只能说不推荐,不赞成,不支持。
看看UserController里面的具体代码吧,这个类上面有两个属性,RequestMapping 和 RestController,RequestMapping 其实就是设置访问路径。类上面,方法上面都有哦。前面静态页面发出请求的url中user/findall、user/remove之类的,原来就是来自这里。如果这里变化了,静态页面中的url也得跟着变化。
而RestController 这个属性有两个含义,一是表示这个类是前端可以直接调用,甚至别的系统也可以调用。还有就是某个方法返回的对象是类或者集合。由于有这个属性,系统会把返回对象转换为json格式的String。这里的findAll方法就是这样的。如图所示,妥妥的json格式嘛。
Controller 这一层是通过访问 Service 层来获取数据。这里你会注意到Controller 调用Service的方法时,不是用new的方式创建对象,而是通过@Autowired属性自动装配方式创建对象。简单一点说,就是框架帮着实例化对象。
在Spring时代,有些类必须通过配置文件加载进来,所以这样实例化方便。虽然Springboot大大减少了配置文件,Springboot还是继承着一做法。通过@Autowired创建类也还有些好处的,比如效率高了。这种方式还可以让我们的系统应对更为复杂的业务场景哦。
其实,如果对这些不是太明白,也没关系,可以慢慢理解.相信你,学习Springboot是来日方长,现在知道这个搞法就行了,既然学习Springboot,就遵守Springboot方式。不要自己new对象。后面的Service调repository也是这么个搞法。一旦习惯这种模式,感觉也挺好的。
接下来是Service层,这一层主要业务逻辑都在这里实现,简单一点理解,这里是核心代码,关键代码。比如一个库存系统,货物出库。生成订单,计算库存,订单消息等等,都应该写在这里。不过,下面的UserService非常简单。
package com.springboot.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springboot.repository.sqlserver.UserRepository;
import com.springboot.comm.DateTimeUtile;
import com.springboot.entity.MJson;
import com.springboot.entity.sqlserver.User;
@Service
public class UserService {
@Autowired
UserRepository db;
public List<User> findAll()
{
return db.findAll();
}
public MJson remove(String id)
{
MJson m = new MJson();
//
db.deleteById(id);
return m;
}
public MJson add(String name,float gdata)
{
MJson m = new MJson();
User u = new User();
u.name = name;
u.gdate = DateTimeUtile.getNowDate();
u.gdata = gdata;
db.save(u);
return m;
}
}
到这里,有人可能就说了,这么简单的的Service,可不可以不要了?当然可以,确实存在Controller直调 Repository层里面的方法的情况。很多业务特简单的项目就是这么干的,能实现客户需求就行嘛。不过,即便是最简单的业务,还是写Service的好,规范,规则,规矩嘛。
对于不同的业务,不同项目,Service层可以说是各种复杂,但是好像太多东西可以扯了,具体业务具体写法吧。Service层是调用JPA的 Repository 来获取数据,调法和Controller调Service类似,也是上面提到的@Autowired。
看看UserRepository类,代码很少,但是Repository有很多方法可以供Service调用,什么增加,删除,查询全部,按个条件查询等等,应有尽有的感觉。
package com.springboot.repository.sqlserver;
import org.springframework.data.jpa.repository.JpaRepository;
import com.springboot.entity.sqlserver.User;
public interface UserRepository extends JpaRepository<User, String>
{
//这里可以增加自己方法,但是都是框架帮你实现
//User findByNamee(String name);
@Transactional
@Modifying
@Query(value = "delete from t_test_data",nativeQuery = true)
int delAllData();
}
很明显,Repository是通过Springboot的JAP框架实现了很多功能。当然,我们也可以自己写SQL语句来实现一些特殊的功能,比如上面这个delAllData方法就是删除全表数据的方法。因为jpa所提供的删除全表数据是个坑,有机会再具体写写。如果不知道JPA的,可以简单的认为整合在Springboot中的Hibernate框架的一部分。
当然,Repository 这个层也有很多人用Mybatis 这个从本质上没啥区别,用哪个其实都所谓,萝卜白菜,各有所爱嘛。这里只说Hibernate方式,对于初学者,讲一种方法实现功能,也许更容易理解。
说了这么多,都是理想状态,如果还有人看的不太明白,也正常,不要去理解,不要去想为什么。这样活就是这么干,就是这么实现。代码看的多了,日子长了,也许在某个不经意间就豁然开朗了。
获取数据的整个流程到这里算是结束了。
在整个流程中,作为数据载体的实体类,这个也简单,但是也容易掉进坑里。
package com.springboot.entity.sqlserver;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity //实体类标识
@Table(name = "t_test_data") // t_test_data 就是上面在数据库建的表
public class User
{
@Id //表示唯一字段
@GenericGenerator(name = "id-generator", strategy = "uuid") //id生成方式 guid
@GeneratedValue(generator = "id-generator")
@Column(name="id") //字段名
public String id;
@Column(name="name") //字段名
public String name;
@Column(name="gdate")
public Date gdate;
@Column(name="gdata")
public float gdata;
}
实体类与数据库的表结构对应起来即可,字段名称和数据类型都得对应。如果id字段想自己赋值,改成如下模式
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
@Column(name = "id")
public String id;
还有,如果实体类中的某个属性与数据库没关系。
@Transient
public boolean mid = false;
当然大部分人都是把变量写成私有成员模式,然后增加get和set方法,如下
private String pid;
public void setPid(String pid){
this.pid = pid;
}
public String getPid(){
return this.pid;
}
还有一种的做法,只定义私有变量,private 这一部分,get和set 方法都是通过一个lombok组件自动生成。这个属于比较高级玩法,可以慢慢来,也不是必须的。
在Repository中,操作数据库方法有很多,这里只演示两个简单的操作,剩下的慢慢摸索。知识的掌握不光是学习,更多是是靠工作中的积累。很多东西看多了,用的多了自然明白了。所谓的走的路多,碰的鬼多。
在Repository中,不管是查询还是修改,框架都允许自己写SQL语句,活干多了,就会发现其实所谓的需求变化,其实就是SQL语句的变化。在UserRepository类中,就有个自定义删除全部数据方法,这个方法没有被调用。有兴趣的可以自己在Query.html 页面中加一个按钮调用这个方法试试。
最后注意一点 pom文件跟前一个项目相比,增加数据库驱动jar包的依赖。这里贴一下 dependencies 部分了。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 增加部分 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!-- sqlserver 驱动jar 包 -->
</dependencies>
如果不是Sqlserver数据库,比如Mysql,Oracle之类的写法又太不一样,不过基本都差不都。
好了,数据库操作基本说完了,可能还有些内容没说到的,欢迎下面留言。
一起学习,一起交流,又何必打赏。