學習springboot第2步,Hibernate操作數據庫

      關於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實時數據查詢  &nbsp;&nbsp;
   <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之類的寫法又太不一樣,不過基本都差不都。

好了,數據庫操作基本說完了,可能還有些內容沒說到的,歡迎下面留言。

  一起學習,一起交流,又何必打賞。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章