整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JavaWeb連接MySQL數(shù)據(jù)庫(kù)最細(xì)圖解

          JavaWeb連接MySQL數(shù)據(jù)庫(kù)最細(xì)圖解

          avaWeb連接MySQL數(shù)據(jù)庫(kù)的方式有很多,首先我們講解JDBC的配置方法

          一、JDBC的配置方法

          1、什么是JDBC

          什么是JDBC嘞?JDBC代表Java數(shù)據(jù)庫(kù)連接(Java Database Connectivity),它是用于Java編程語(yǔ)言和數(shù)據(jù)庫(kù)之間的數(shù)據(jù)庫(kù)無(wú)關(guān)連接的標(biāo)準(zhǔn)Java API,

          換句話說(shuō):JDBC是用于在Java語(yǔ)言編程中與數(shù)據(jù)庫(kù)連接的API。

          JDBC庫(kù)包括通常與數(shù)據(jù)庫(kù)使用相關(guān),如下面提到的每個(gè)任務(wù)的API -

          • 連接到數(shù)據(jù)庫(kù)
          • 創(chuàng)建SQL或MySQL語(yǔ)句
          • 在數(shù)據(jù)庫(kù)中執(zhí)行SQL或MySQL查詢
          • 查看和修改結(jié)果記錄

          從根本上說(shuō),JDBC是一個(gè)規(guī)范,它提供了一整套接口,允許以一種可移植的訪問(wèn)底層數(shù)據(jù)庫(kù)API。 Java可以用它來(lái)編寫不同類型的可執(zhí)行文件,如 -

          • Java應(yīng)用程序
          • Java Applet
          • Java Servlets
          • Java ServerPages(JSP)
          • 企業(yè)級(jí)JavaBeans(EJB)

          所有這些不同的可執(zhí)行文件都能夠使用JDBC驅(qū)動(dòng)程序來(lái)訪問(wèn)數(shù)據(jù)庫(kù),并用于存儲(chǔ)數(shù)據(jù)到數(shù)據(jù)庫(kù)中。

          JDBC提供與ODBC相同的功能,允許Java程序包含與數(shù)據(jù)庫(kù)無(wú)關(guān)的代碼(同樣的代碼,只需要指定使用的數(shù)據(jù)庫(kù)類型,不需要重修改數(shù)據(jù)庫(kù)查詢或操作代碼)。

          2、下載配置

          (1)首先我們到MySQL的官網(wǎng)去下載支持程序“MySQL Connector/J”(MySQL官方的JDBC驅(qū)動(dòng)程序)

          這里附上一鍵直達(dá)的鏈接:MySQL :: Download MySQL Connector/J (Archived Versions)

          首先打開(kāi)MySQL官網(wǎng),點(diǎn)擊DOWNLOADS

          之后我們點(diǎn)擊MySQL Community(GPL) Downloads

          點(diǎn)擊Connector/J

          點(diǎn)擊Archives

          按照?qǐng)D片進(jìn)行選擇并下載(這里我們不可以選擇上方的那個(gè)文件,因?yàn)樯厦婺莻€(gè)文件是Liunx、Dabian等系統(tǒng)的文件,下面的文件才是Windows版本的!!!

          至此,我們下載完成。

          (2)接下來(lái)我們進(jìn)行文件配置。

          我們將下載的壓縮包進(jìn)行解壓,在生成的文件中會(huì)有一個(gè)名為mysql-connector-java-8.0.28.jar的文件。

          我們要在需要與MySQL連接的項(xiàng)目中建立一個(gè)lib文件夾,并將.jar文件復(fù)制粘貼到此文件夾下(也可以直接進(jìn)行拖拽)

          之后我們用右鍵,按照?qǐng)D片上的步驟操作,添加驅(qū)動(dòng)程序路徑(成功后會(huì)多出一個(gè)

          文件)

          到這里不要著急,下面我們將.jar包導(dǎo)入到你電腦Tomcat文件根目錄下的lib文件夾內(nèi),這樣,你就完成了所有配置!

          (3)接下來(lái)我們注冊(cè)JDBC驅(qū)動(dòng)程序

          連接數(shù)據(jù)庫(kù)時(shí),需要將數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序注冊(cè)到j(luò)dbc的驅(qū)動(dòng)管理器中。

          調(diào)用Class.forName()方法例如:Class.forName(“com.mysql.jdbc.Driver”);當(dāng)jdbc驅(qū)動(dòng)程序mysql-connector-java-5.0.5-bin.jar為6.x版本以上時(shí),調(diào)用為Class.forName(“com.mysql.cj.jdbc.Driver”);

          (4)基于數(shù)據(jù)庫(kù)連接的URL創(chuàng)建連接

          雖然不同數(shù)據(jù)庫(kù)廠商的URL不完全相同,但是都符合一個(gè)基本的格式,即“jdbc協(xié)議+IP地址或域名+端口號(hào)+數(shù)據(jù)庫(kù)名稱”。

          創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí),需要使用DriverManager類中g(shù)etConnection()的靜態(tài)方法,方法聲明如下:DriverManager.getConnection(String url,String username,password);

          二、使用JDBC的方法使JavaWeb連接MySQL數(shù)據(jù)庫(kù)

          下面我們寫一個(gè)JSP代碼,用來(lái)驗(yàn)證是否可以連接MySQL數(shù)據(jù)庫(kù)。

          <%@page import="java.sql.DriverManager"%><%@page import="java.sql.DriverAction"%><%@page import="java.sql.Connection"%><%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta http-equiv="Content-Type" content:"text/html" charset="UTF-8"><title>MySQL</title></head><body>	<%	try {		Class.forName("com.mysql.cj.jdbc.Driver"); //顯示聲明將數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序注冊(cè)到j(luò)dbc的驅(qū)動(dòng)管理器中		String url="jdbc:mysql://localhost:3306/text"; //數(shù)據(jù)庫(kù)名稱為text(需要提前在MySQL里面建立text數(shù)據(jù)庫(kù))		String username="root"; //數(shù)據(jù)庫(kù)用戶名		String password="123456"; //數(shù)據(jù)庫(kù)密碼			Connection conn=DriverManager.getConnection(url, username, password); //連接數(shù)據(jù)庫(kù)		out.print("數(shù)據(jù)庫(kù)連接成功!");		conn.close();	} catch (Exception e) {		out.print("數(shù)據(jù)庫(kù)連接失敗!");		out.print("錯(cuò)誤信息:" + e.toString());	}	%> </body></html>

          PS:這里需要注意的是我們自己使用時(shí)一定要修改成自己MySQL的用戶名和密碼,保證可以正常連接數(shù)據(jù)庫(kù)。并且我們連接的數(shù)據(jù)庫(kù)一定要存在!!!

          三、進(jìn)行實(shí)際操作

          1、創(chuàng)建首頁(yè)(login.jsp)

          首先需要?jiǎng)?chuàng)建一個(gè)新的首頁(yè),首頁(yè)可以顯示用戶名,密碼,登錄按鈕等。代碼如下:

          <%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>歡迎登錄</title></head><body>	<div style="text-align: center; margin-top: 120px">		<form action="LoginServet" method="post">			<table style="margin-left: 40%">				<h1>登陸</h1>				<tr>					<td>登錄名:</td>					<td><input name="username" type="text" size="21"></td>				</tr>				<tr>					<td>密碼:</td>					<td><input name="password" type="password" size="21"></td>				</tr>			</table>			<input type="submit" value="登錄">			<input type="reset"value="重置">		</form>		<br>	</div></body></html>

          效果如下:

          2、創(chuàng)建LoginServlet.java文件

          接下來(lái)我們創(chuàng)建LoginServlet.java文件。代碼如下:

          package com.sdbi.servlet; import java.io.IOException;  import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;   import com.sdbi.dao.userDao;import com.sdbi.entity.User; @WebServlet("/LoginServet")public class LoginServet extends HttpServlet { 	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		String account=request.getParameter("username");		String passWord=request.getParameter("password");				HttpSession session=request.getSession();		String username=request.getParameter("username");		String password=request.getParameter("password");		userDao userDao=new userDao();					User user=(User)userDao.login(username, password);		if (user !=null) {			session.setAttribute(username, user);			request.getRequestDispatcher("check.jsp").forward(request, response);					}else {			request.getRequestDispatcher("failed.jsp").forward(request, response);		}	} 	protected void doPost(HttpServletRequest request, HttpServletResponse response)			throws ServletException, IOException { 		doGet(request, response);	} }

          4、創(chuàng)建UserDao.java文件

          代碼如下:

          package com.sdbi.dao; import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;   import com.mysql.cj.protocol.Resultset.Concurrency;import com.sdbi.entity.User; import util.DButil; public class userDao { 	public User login(String username,String password) {		User u=null;		Connection connection=null;		PreparedStatement pstmt=null;		ResultSet resultSet=null;		try {			connection=DButil.getcon();			String sql="select * from user where username=? and password=?";			pstmt=(PreparedStatement) connection.prepareStatement(sql);			pstmt.setString(1, username);			pstmt.setString(2, password);			resultSet=pstmt.executeQuery();			if (resultSet.next()) {				u=new User();				u.setUsername(resultSet.getString("username"));				u.setPassword(resultSet.getString("password"));				System.out.println("登錄成功!");			} else {				System.out.println("用戶名或者密碼錯(cuò)誤!");			} 		} catch (SQLException e) {			e.printStackTrace(); 		} finally {			//DBUtil.close(pstmt, connection); 		}		return u;	} 	public boolean addUser(User user) {		 Connection connection=null;		 PreparedStatement psmt=null;		 try {			connection=DButil.getcon();			String sql="insert into user(username,password);";			psmt=(PreparedStatement) connection.prepareStatement(sql);			 psmt.setString(1, user.getUsername());			psmt.setString(2,user.getPassword());			psmt.executeUpdate();																			} catch (SQLException e) {			e.printStackTrace();			return false;					}finally {			//DBUtil.close(psmt, connection);		}		 return true;	} }

          5、創(chuàng)建User.java文件

          package com.sdbi.entity; public class User {	private String username;	private String password;	public String getUsername() {		return username;	}	public void setUsername(String username) {		this.username=username;	}	public String getPassword() {		return password;	}	public void setPassword(String password) {		this.password=password;	}				 }

          6、創(chuàng)建check.jsp文件

          <%@page import="java.sql.ResultSet"%><%@page import="java.sql.PreparedStatement"%><%@page import="java.sql.DriverManager"%><%@page import="java.sql.Connection"%><%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>所有用戶信息</title></head><body>	<center>		<h3>所有用戶信息</h3>		<table border="1">			<tr>				<th>賬戶</th>				<th>密碼</th>			</tr>			<%			//加載、注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序			Class.forName("com.mysql.cj.jdbc.Driver"); 			//數(shù)據(jù)庫(kù)連接字符串			String url="jdbc:mysql://localhost:3306/text";			//用戶名			String username="root";			//密碼			String password="123456";			//數(shù)據(jù)庫(kù)連接			Connection conn=DriverManager.getConnection(url, username, password);			//構(gòu)造sql語(yǔ)句			String sql="select * from user";			//獲取數(shù)據(jù)庫(kù)操作對(duì)象(PreparedStatement對(duì)象)			PreparedStatement pstmt=conn.prepareStatement(sql); 			ResultSet rs=pstmt.executeQuery(); 			//循環(huán)前準(zhǔn)備變量			String uname=null;			String upassword=null;			while (rs.next()) {				uname=rs.getString("username");				upassword=rs.getString("password");			%>			<tr>				<td><%=uname%></td>				<th><%=upassword%></th>			</tr> 			<%			}			//釋放對(duì)象			if (pstmt !=null) {			pstmt.close();			}			if (conn !=null) {			pstmt.close();			}			if (rs !=null) {			rs.close();			}			%>			</center>		</table></body></html>

          7、創(chuàng)建failed.jsp文件

          <%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>登陸失敗</title></head><body>	<h1>失敗</h1><br />	<a href="login.jsp">請(qǐng)重新登錄</a></body></html>

          8、創(chuàng)建所需要的數(shù)據(jù)庫(kù)連接

          9、登錄用戶


          如果本文對(duì)你有幫助,別忘記給我個(gè)3連 ,點(diǎn)贊,轉(zhuǎn)發(fā),評(píng)論,,咱們下期見(jiàn)。

          收藏 等于白嫖,點(diǎn)贊才是真情。



          原文 https://www.cnblogs.com/soosoo/p/16219491.html

          先說(shuō)明,由于是8版本的數(shù)據(jù)庫(kù),所以配置類的寫法上與5版本的有所區(qū)別,需要注意,同時(shí)用idea或eclipse時(shí)需要導(dǎo)入jar包,jar包的下載鏈接:

          https://dev.mysql.com/get/archives/mysql-connector-java-8.0/mysql-connector-java-8.0.28.zip

          如果想要下載8版本不同的jar包只需要修改8.0.28為指定版本即可。

          idea導(dǎo)入jar包的方法如下:

          然后是代碼部分,首先先建表:

          CREATE TABLE `train_message` (
                                           `id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
                                           `train_name` varchar(20) NOT NULL COMMENT '列車名',
                                           `origin` varchar(30) NOT NULL COMMENT '始發(fā)地',
                                           `terminal` varchar(30) NOT NULL COMMENT '終到地',
                                           `departure_time` timestamp NOT NULL COMMENT '出站時(shí)間',
                                           `state` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '正常' COMMENT '列車狀態(tài)',
                                           PRIMARY KEY (`id`)
          ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb3

          然后創(chuàng)建連接的配置類DbConfig.java,localhost是本機(jī)的ip地址,如果有服務(wù)器就填服務(wù)器的ip地址,message是數(shù)據(jù)庫(kù)的名字,這里一張圖說(shuō)下有很多新手誤解的名字

          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.SQLException;
          
          /**
           *  數(shù)據(jù)庫(kù)配置類
           *  @author 景苒
           */
          public class DbConfig {
              public Connection dbConfig() throws SQLException {
                  try {
                      Class.forName("com.mysql.cj.jdbc.Driver");
                  }catch (Exception e) {
                      System.out.print("加載驅(qū)動(dòng)失敗!");
                      e.printStackTrace();
                  }
                  String url="jdbc:mysql://localhost:3306/message?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true";
                  String user="root";
                  String password="123456";
                  return DriverManager.getConnection(url, user, password);
              }
          }

          然后寫下主函數(shù)Main.java,這里主函數(shù)的函數(shù)體可以在最后再寫,需要什么功能就把注釋打開(kāi)就好,快捷注釋的方法,選中這句話,按ctrl加/,就能全注釋了。

          import java.sql.SQLException;
          
          /**
           * 主函數(shù),調(diào)用功能
           * @author 景苒
           */
          public class Main {
              public static void main(String[] args) throws SQLException {
          //        new GetMessage().getMessage();
          //        new UpdateTrainState().updateTrainState();
          //        new InsertTrain().insertTrain();
          //        new GetNumber().getNumber();
              }
          }

          然后是每個(gè)的功能:

          1.查詢沈陽(yáng)到武漢的所有列車信息,按出發(fā)時(shí)間先后排序

          建GetMessage.java類

          import java.sql.Connection;
          import java.sql.PreparedStatement;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          
          /**
           * 查詢沈陽(yáng)到武漢的所有列車信息,按出發(fā)時(shí)間先后排序
           * @author 景苒
           */
          public class GetMessage {
              public void getMessage() throws SQLException {
                  Connection con=new DbConfig().dbConfig();
                  String sql="select * from `train_message` where origin=? and terminal=? ORDER BY departure_time ASC";
                  String origin="沈陽(yáng)";
                  String terminal="武漢";
                  PreparedStatement ps=con.prepareStatement(sql);
                  ps.setString(1, origin);
                  ps.setString(2, terminal);
                  ResultSet rs=ps.executeQuery();
                  try {
                      while (rs.next()) {
                          System.out.println("列車名:" + rs.getString("train_name")
                                  + " 始發(fā)站:" + rs.getString("origin")
                                  + " 終到站:" + rs.getString("terminal")
                                  + " 出發(fā)時(shí)間:" + rs.getString("departure_time")
                                  + " 列車狀態(tài):" + rs.getString("state"));
                      }
                  }catch (SQLException e) {
                      e.printStackTrace();
                  }finally {
                      ps.close();
                      con.close();
                  }
              }
          }

          2.修改T2255列車的狀態(tài)為停運(yùn)

          建UpdateTrainState.java類

          import java.sql.Connection;
          import java.sql.SQLException;
          import java.sql.Statement;
          
          /**
           * 修改T2255列車的狀態(tài)為停運(yùn)
           * @author 景苒
           */
          public class UpdateTrainState {
              public void updateTrainState() throws SQLException {
                  Connection con=new DbConfig().dbConfig();
                  String sql="UPDATE `train_message` SET state='停運(yùn)' WHERE train_name='T2255'";
                  Statement statement=con.createStatement();
                  try {
                      int i=statement.executeUpdate(sql);
                      if (i > 0) {
                          System.out.println("更新成功");
                      }else {
                          System.out.println("更新失敗");
                      }
                  }catch (SQLException e) {
                      e.printStackTrace();
                  }finally {
                      statement.close();
                      con.close();
                  }
              }
          }

          3.新增一輛列車信息(自己輸入)

          建InsertTrain.java類

          import java.sql.Connection;
          import java.sql.PreparedStatement;
          import java.sql.SQLException;
          import java.util.Scanner;
          
          /**
           * 新增一輛列車信息(自己輸入)
           * 始發(fā)時(shí)間為timestamp類型,輸入時(shí)需要確保格式正確,如:2019-01-01 00:00:00
           * @author 景苒
           */
          public class InsertTrain {
              public void insertTrain() throws SQLException {
                  Connection con=new DbConfig().dbConfig();
                  Scanner scanner=new Scanner(System.in);
                  String sql="insert into `train_message` values(null, ?, ?, ?, ?, default)";
                  System.out.print("請(qǐng)輸入列車名:");
                  String trainName=scanner.nextLine();
                  System.out.print("請(qǐng)輸入始發(fā)站:");
                  String origin=scanner.nextLine();
                  System.out.print("請(qǐng)輸入終到站:");
                  String terminal=scanner.nextLine();
                  System.out.print("請(qǐng)輸入始發(fā)時(shí)間:");
                  String departureTime=scanner.nextLine();
                  PreparedStatement ps=con.prepareStatement(sql);
                  ps.setString(1, trainName);
                  ps.setString(2, origin);
                  ps.setString(3, terminal);
                  ps.setString(4, departureTime);
                  try {
                      int i=ps.executeUpdate();
                      if (i > 0) {
                          System.out.println("添加成功");
                      }else {
                          System.out.println("添加失敗");
                      }
                  }catch (SQLException e) {
                      e.printStackTrace();
                  }finally {
                      ps.close();
                      con.close();
                  }
              }
          }

          4.查詢狀態(tài)為正常的列車數(shù)量

          建GetNumber.java類

          import java.sql.Statement;
          
          /**
           * 查詢狀態(tài)為正常的列車數(shù)量
           * @author 景苒
           */
          public class GetNumber {
              public void getNumber() throws SQLException {
                  Connection con=new DbConfig().dbConfig();
                  String sql="select count(state) from `train_message` where state='正常'";
                  Statement statement=con.createStatement();
                  try {
                      ResultSet resultSet=statement.executeQuery(sql);
                      while (resultSet.next()) {
                          System.out.println("狀態(tài)為正常的列車數(shù)量為:" + resultSet.getInt(1));
                      }
                  }catch (SQLException e){
                      e.printStackTrace();
                  }finally {
                      statement.close();
                      con.close();
                  }
              }
          }

          最后附上navicat的屬性結(jié)構(gòu)圖和樣例插入的語(yǔ)句

          數(shù)據(jù)根據(jù)自己需求自行寫入幾個(gè)就行,以上就是java連接mysql數(shù)據(jù)庫(kù)的實(shí)例代碼,eclipse也大同小異,就導(dǎo)入jar包的方式不同。

          文章來(lái)自https://www.cnblogs.com/jingran/p/16120104.html

          數(shù)據(jù)庫(kù)已經(jīng)越來(lái)越被人們熟知,同時(shí)也在許多企業(yè)中得到了應(yīng)用,但是由于市面上沒(méi)有統(tǒng)一的圖查詢語(yǔ)言標(biāo)準(zhǔn),所以有部分開(kāi)發(fā)者對(duì)于不同圖數(shù)據(jù)庫(kù)的用法存在著疑問(wèn)。因此本文作者對(duì)市面上主流的幾款圖數(shù)據(jù)庫(kù)進(jìn)行了一番分析,并以查詢操作為例進(jìn)行深入介紹。

          文章的開(kāi)頭我們先來(lái)看下什么是圖數(shù)據(jù)庫(kù),根據(jù)維基百科的定義:圖數(shù)據(jù)庫(kù)是使用圖結(jié)構(gòu)進(jìn)行語(yǔ)義查詢的數(shù)據(jù)庫(kù),它使用節(jié)點(diǎn)、邊和屬性來(lái)表示和存儲(chǔ)數(shù)據(jù)

          雖然和關(guān)系型數(shù)據(jù)庫(kù)存儲(chǔ)的結(jié)構(gòu)不同(關(guān)系型數(shù)據(jù)庫(kù)為表結(jié)構(gòu),圖數(shù)據(jù)庫(kù)為圖結(jié)構(gòu)),但不計(jì)各自的性能問(wèn)題,關(guān)系型數(shù)據(jù)庫(kù)可以通過(guò)遞歸查詢或者組合其他 SQL 語(yǔ)句(Join)完成圖查詢語(yǔ)言查詢節(jié)點(diǎn)關(guān)系操作。得益于 1987 年 SQL 成為國(guó)際標(biāo)準(zhǔn)化組織(ISO)標(biāo)準(zhǔn),關(guān)系型數(shù)據(jù)庫(kù)行業(yè)得到了很好的發(fā)展。同 60、70 年代的關(guān)系型數(shù)據(jù)庫(kù)類似,圖數(shù)據(jù)庫(kù)這個(gè)領(lǐng)域的查詢語(yǔ)言目前也沒(méi)有統(tǒng)一標(biāo)準(zhǔn),雖然 19 年 9 月經(jīng)過(guò)國(guó)際 SQL 標(biāo)準(zhǔn)委員會(huì)投票表決,決定將圖查詢語(yǔ)言(Graph Query Language)納為一種新的數(shù)據(jù)庫(kù)查詢語(yǔ)言,但 GQL 的制定仍需要一段時(shí)間。

          鑒于市面上沒(méi)有統(tǒng)一的圖查詢語(yǔ)言標(biāo)準(zhǔn),在本文中我們選取市面上主流的幾款圖查詢語(yǔ)言來(lái)分析一波用法,由于篇幅原因本文旨在簡(jiǎn)單介紹圖查詢語(yǔ)言和常規(guī)用法,更詳細(xì)的內(nèi)容將在進(jìn)階篇中講述。

          圖查詢語(yǔ)言·介紹

          圖查詢語(yǔ)言 Gremlin

          Gremlin 是 Apache ThinkerPop 框架下的圖遍歷語(yǔ)言。Gremlin 可以是的也可以是命令性的。雖然 Gremlin 是基于 Groovy 的,但具有許多語(yǔ)言變體,允許開(kāi)發(fā)人員以 Java、JavaScript、Python、Scala、Clojure 和 Groovy 等許多現(xiàn)代編程語(yǔ)言原生編寫 Gremlin 查詢

          支持圖數(shù)據(jù)庫(kù):Janus Graph、InfiniteGraph、Cosmos DB、DataStax Enterprise(5.0+) 、Amazon Neptune

          圖查詢語(yǔ)言 Cypher

          Cypher 是一個(gè)描述性的圖形查詢語(yǔ)言,允許不必編寫圖形結(jié)構(gòu)的遍歷代碼對(duì)圖形存儲(chǔ)有表現(xiàn)力和效率的查詢,和 SQL 很相似,Cypher 語(yǔ)言的關(guān)鍵字不區(qū)分大小寫,但是屬性值,標(biāo)簽,關(guān)系類型和變量是區(qū)分大小寫的。

          支持圖數(shù)據(jù)庫(kù): Neo4j、RedisGraph、AgensGraph

          圖查詢語(yǔ)言 nGQL

          nGQL 是一種類 SQL 的聲明型的文本查詢語(yǔ)言,nGQL 同樣是關(guān)鍵詞大小寫不敏感的查詢語(yǔ)言,目前支持模式匹配、聚合運(yùn)算、圖計(jì)算,可無(wú)嵌入組合語(yǔ)句。

          支持圖數(shù)據(jù)庫(kù):Nebula Graph

          圖查詢語(yǔ)言·術(shù)語(yǔ)篇

          在比較這 3 個(gè)圖查詢語(yǔ)言之前,我們先來(lái)看看他們各自的術(shù)語(yǔ),如果你翻閱他們的文檔會(huì)經(jīng)常見(jiàn)到下面這些“關(guān)鍵字”,在這里我們不講用法,只看這些圖數(shù)據(jù)庫(kù)常用概念在這 3 個(gè)圖數(shù)據(jù)庫(kù)文檔中的叫法。

          術(shù)語(yǔ)GremlinCyphernGQL點(diǎn)VertexNodeVertex邊EdgeRelationshipEdge點(diǎn)類型LabelLabelTag邊類型labelRelationshipTypeedge type點(diǎn) IDvidid(n)vid邊 IDeidid?無(wú)插入addcreateinsert刪除dropdeletedelete / drop更新屬性setPropertysetupdate

          我們可以看到大體上對(duì)點(diǎn)和邊的叫法類似,只不過(guò) Cypher 中直接使用了 Relationship 關(guān)系一詞代表邊。其他的術(shù)語(yǔ)基本都非常直觀。

          圖查詢語(yǔ)言·實(shí)操篇

          上面說(shuō)了一通術(shù)語(yǔ)之類的“干貨”之后,是時(shí)候展示真正的技術(shù)了——來(lái)個(gè)具體一點(diǎn)的例子,在具體的例子中我們將會(huì)分析 Gremlin、Cypher、nGQL 的用法不同。

          示例圖:The Graphs of Gods

          實(shí)操示例使用了 Janus Graph 的示例圖 The Graphs of Gods。該圖結(jié)構(gòu)如下圖所示,描述了羅馬萬(wàn)神話中諸神關(guān)系。

          插入數(shù)據(jù)

          復(fù)制代碼

          # 插入點(diǎn)## nGQLnebula> INSERT VERTEX character(name, age, type) VALUES hash("saturn"):("saturn", 10000, "titan"), hash("jupiter"):("jupiter", 5000, "god");## Gremlingremlin> saturn=g.addV("character").property(T.id, 1).property('name', 'saturn').property('age', 10000).property('type', 'titan').next();==>v[1]gremlin> jupiter=g.addV("character").property(T.id, 2).property('name', 'jupiter').property('age', 5000).property('type', 'god').next();==>v[2]gremlin> prometheus=g.addV("character").property(T.id, 31).property('name',  'prometheus').property('age', 1000).property('type', 'god').next();==>v[31]gremlin> jesus=g.addV("character").property(T.id, 32).property('name',  'jesus').property('age', 5000).property('type', 'god').next();==>v[32]## Cyphercypher> CREATE (src:character {name:"saturn", age: 10000, type:"titan"})cypher> CREATE (dst:character {name:"jupiter", age: 5000, type:"god"})# 插入邊## nGQLnebula> INSERT EDGE father() VALUES hash("jupiter")->hash("saturn"):();## Gremlingremlin> g.addE("father").from(jupiter).to(saturn).property(T.id, 13);==>e[13][2-father->1]## Cyphercypher> CREATE (src)-[rel:father]->(dst)

          在數(shù)據(jù)插入這塊,我們可以看到 nGQL 使用 INSERT VERTEX 插入點(diǎn),而 Gremlin 直接使用類函數(shù)的 g.addV() 來(lái)插入點(diǎn),Cypher 使用 CREATE 這個(gè) SQL 常見(jiàn)關(guān)鍵詞來(lái)創(chuàng)建插入的點(diǎn)。在點(diǎn)對(duì)應(yīng)的屬性值方面,nGQL 通過(guò) VALUES 關(guān)鍵詞來(lái)賦值,Gremlin 則通過(guò)操作 .property() 進(jìn)行對(duì)應(yīng)屬性的賦值,Cypher 更直觀直接在對(duì)應(yīng)的屬性值后面跟上想對(duì)應(yīng)的值。

          在邊插入方面,可以看到和點(diǎn)的使用語(yǔ)法類似,只不過(guò)在 Cypher 和 nGQL 中分別使用 -[]-> 和 **-> 來(lái)表示關(guān)系,而 Gremlin 則用 to() ** 關(guān)鍵詞來(lái)標(biāo)識(shí)指向關(guān)系,在使用這 3 種圖查詢語(yǔ)言的圖數(shù)據(jù)庫(kù)中的邊均為有向邊,下圖左邊為有向邊,右邊為無(wú)向邊。

          刪除數(shù)據(jù)

          復(fù)制代碼

          # nGQLnebula> DELETE VERTEX hash("prometheus");# Gremlingremlin> g.V(prometheus).drop();# Cyphercypher> MATCH (n:character {name:"prometheus"}) DETACH DELETE n 

          這里,我們可以看到大家的刪除關(guān)鍵詞都是類似的:Delete 和 Drop,不過(guò)這里需要注意的是上面術(shù)語(yǔ)篇中提過(guò) nGQL 中刪除操作對(duì)應(yīng)單詞有 Delete 和 Drop ,在 nGQL 中 Delete 一般用于點(diǎn)邊,Drop 用于 Schema 刪除,這點(diǎn)和 SQL 的設(shè)計(jì)思路是一樣的。

          更新數(shù)據(jù)

          復(fù)制代碼

          # nGQLnebula> UPDATE VERTEX hash("jesus") SET character.type='titan';# Gremlingremlin> g.V(jesus).property('age', 6000);==>v[32]# Cyphercypher> MATCH (n:character {name:"jesus"}) SET n.type='titan';

          可以看到 Cypher 和 nGQL 都使用 SET 關(guān)鍵詞來(lái)設(shè)置點(diǎn)對(duì)應(yīng)的類型值,只不過(guò) nGQL 中多了 UPDATE 關(guān)鍵詞來(lái)標(biāo)識(shí)操作,Gremlin 的操作和查看點(diǎn)操作類似,只不過(guò)增加了變更 property 值操作,這里我們注意到的是,Cypher 中常見(jiàn)的一個(gè)關(guān)鍵詞便是 MATCH,顧名思義,它是一個(gè)查詢關(guān)鍵詞,它會(huì)去選擇匹配對(duì)應(yīng)條件下的點(diǎn)邊,再進(jìn)行下一步操作。

          查看數(shù)據(jù)

          復(fù)制代碼

          # nGQLnebula> FETCH PROP ON character hash("saturn");===================================================| character.name | character.age | character.type |===================================================| saturn         | 10000         | titan          |---------------------------------------------------# Gremlingremlin> g.V(saturn).valueMap();==>[name:[saturn],type:[titan],age:[10000]]# Cyphercypher> MATCH (n:character {name:"saturn"}) RETURN properties(n)  ╒════════════════════════════════════════════╕  │"properties(n)"                             │  ╞════════════════════════════════════════════╡  │{"name":"saturn","type":"titan","age":10000}│  └────────────────────────────────────────────┘

          在查看數(shù)據(jù)這塊,Gremlin 通過(guò)調(diào)取 valueMap() 獲得對(duì)應(yīng)的屬性值,而 Cypher 正如上面更新數(shù)據(jù)所說(shuō),依舊是 MATCH 關(guān)鍵詞來(lái)進(jìn)行對(duì)應(yīng)的匹配查詢?cè)偻ㄟ^(guò) RETURN 返回對(duì)應(yīng)的數(shù)值,而 nGQL 則對(duì) saturn 進(jìn)行 hash 運(yùn)算得到對(duì)應(yīng) VID 之后去獲取對(duì)應(yīng) VID 的屬性值。

          查詢 hercules 的父親

          復(fù)制代碼

          # nGQLnebula>  LOOKUP ON character WHERE character.name=='hercules' | \      -> GO FROM $-.VertexID OVER father YIELD $$.character.name;=====================| $$.character.name |=====================| jupiter           |---------------------# Gremlingremlin> g.V().hasLabel('character').has('name','hercules').out('father').values('name');==>jupiter# Cyphercypher> MATCH (src:character{name:"hercules"})-[:father]->(dst:character) RETURN dst.name      ╒══════════╕      │"dst.name"│      ╞══════════╡      │"jupiter" │      └──────────┘

          查詢父親,其實(shí)是一個(gè)查詢關(guān)系 / 邊的操作,這里不做贅述,上面插入邊的時(shí)候簡(jiǎn)單介紹了 Gremlin、Cypher、nGQL 這三種圖數(shù)據(jù)庫(kù)是各自用來(lái)標(biāo)識(shí)邊的關(guān)鍵詞和操作符是什么。

          查詢 hercules 的祖父

          復(fù)制代碼

          # nGQLnebula> LOOKUP ON character WHERE character.name=='hercules' | \     -> GO 2 STEPS FROM $-.VertexID OVER father YIELD $$.character.name;=====================| $$.character.name |=====================| saturn            |---------------------# Gremlingremlin> g.V().hasLabel('character').has('name','hercules').out('father').out('father').values('name');==>saturn# Cyphercypher> MATCH (src:character{name:"hercules"})-[:father*2]->(dst:character) RETURN dst.name      ╒══════════╕      │"dst.name"│      ╞══════════╡      │"saturn"  │      └──────────┘

          查詢祖父,其實(shí)是一個(gè)查詢對(duì)應(yīng)點(diǎn)的兩跳關(guān)系,即:父親的父親,我們可以看到 Gremlin 使用了兩次 out() 來(lái)表示為祖父,而 nGQL 這里使用了 (Pipe 管道) 的概念,用于子查詢。在兩跳關(guān)系處理上,上面說(shuō)到 Gremlin 是用了 2 次 out(),而 Cypher、nGQL 則引入了 step 數(shù)的概念,分別對(duì)應(yīng)到查詢語(yǔ)句的 GO 2 STEP 和 [:father *2],相對(duì)來(lái)說(shuō) Cypher、nGQL 這樣書寫更優(yōu)雅。

          查詢年齡大于 100 的人物

          復(fù)制代碼

          # nGQLnebula> LOOKUP ON character WHERE character.age > 100 YIELD character.name, character.age;=========================================================| VertexID             | character.name | character.age |=========================================================| 6761447489613431910  | pluto          | 4000          |---------------------------------------------------------| -5860788569139907963 | neptune        | 4500          |---------------------------------------------------------| 4863977009196259577  | jupiter        | 5000          |---------------------------------------------------------| -4316810810681305233 | saturn         | 10000         |---------------------------------------------------------# Gremlingremlin> g.V().hasLabel('character').has('age',gt(100)).values('name');==>saturn==>jupiter==>neptune==>pluto# Cyphercypher> MATCH (src:character) WHERE src.age > 100 RETURN src.name      ╒═══════════╕      │"src.name" │      ╞═══════════╡      │  "saturn" │      ├───────────┤      │ "jupiter" │      ├───────────┤      │ "neptune" │      │───────────│      │  "pluto"  │      └───────────┘

          這個(gè)是一個(gè)典型的查詢語(yǔ)句,找尋符合特定條件的點(diǎn)并返回結(jié)果,在 Cypher 和 nGQL 中用 WHRER 進(jìn)行條件判斷,而 Gremlin 延續(xù)了它的“編程風(fēng)”用 gt(100) 表示年大于齡 100 的這個(gè)篩選條件,延伸下 Gremlin 中 eq() 則表示等于這個(gè)查詢條件。

          從一起居住的人物中排除 pluto 本人

          復(fù)制代碼

          # nGQLnebula>  GO FROM hash("pluto") OVER lives YIELD lives._dst AS place | GO FROM $-.place OVER lives REVERSELY WHERE $$.character.name !="pluto" YIELD $$.character.name AS cohabitants;===============| cohabitants |===============| cerberus    |---------------# Gremlingremlin> g.V(pluto).out('lives').in('lives').where(is(neq(pluto))).values('name');==>cerberus# Cyphercypher> MATCH (src:character{name:"pluto"})-[:lives]->()<-[:lives]-(dst:character) RETURN dst.name      ╒══════════╕      │"dst.name"│      ╞══════════╡      │"cerberus"│      └──────────┘

          這是一個(gè)沿指定點(diǎn) Pluto 反向查詢指定邊(居住)的操作,在反向查詢中,Gremlin 使用了 in 來(lái)表示反向關(guān)系,而 Cypher 則更直觀的將指向箭頭反向變成 <- 來(lái)表示反向關(guān)系,nGQL 則用關(guān)鍵詞 REVERSELY 來(lái)標(biāo)識(shí)反向關(guān)系。

          Pluto 的兄弟們居住在哪

          復(fù)制代碼

          # which brother lives in which place?## nGQLnebula> GO FROM hash("pluto") OVER brother YIELD brother._dst AS god | \GO FROM $-.god OVER lives YIELD $^.character.name AS Brother, $$.location.name AS Habitations;=========================| Brother | Habitations |=========================| jupiter | sky         |-------------------------| neptune | sea         |-------------------------## Gremlingremlin> g.V(pluto).out('brother').as('god').out('lives').as('place').select('god','place').by('name');==>[god:jupiter, place:sky]==>[god:neptune, place:sea]## Cyphercypher> MATCH (src:Character{name:"pluto"})-[:brother]->(bro:Character)-[:lives]->(dst)RETURN bro.name, dst.name      ╒═════════════════════════╕      │"bro.name"    │"dst.name"│      ╞═════════════════════════╡      │ "jupiter"    │  "sky"   │      ├─────────────────────────┤      │ "neptune"    │ "sea"    │      └─────────────────────────┘

          這是一個(gè)通過(guò)查詢指定點(diǎn) Pluto 查詢指定邊 brother 后再查詢指定邊 live 的查詢,相對(duì)來(lái)說(shuō)不是很復(fù)雜,這里就不做解釋說(shuō)明了。

          最后,本文只是對(duì) Gremlin、Cypher、nGQL 等 3 個(gè)圖查詢語(yǔ)言進(jìn)行了簡(jiǎn)單的介紹,更復(fù)雜的語(yǔ)法將在本系列的后續(xù)文章中繼續(xù),歡迎在論壇留言交流。


          主站蜘蛛池模板: 国产视频一区二区| 亚洲日韩精品无码一区二区三区| 无码人妻精品一区二区三区99不卡 | 国产传媒一区二区三区呀| 香蕉视频一区二区| 香蕉久久ac一区二区三区| 无码人妻啪啪一区二区| 一区二区精品视频| 天堂资源中文最新版在线一区 | 国产激情无码一区二区| 免费在线视频一区| 国产成人欧美一区二区三区| 国产亚洲一区二区精品| 国产suv精品一区二区33| 狠狠综合久久av一区二区| 国内精品一区二区三区最新| 激情久久av一区av二区av三区| 无码国产精品一区二区免费式芒果| 国精产品一区一区三区| 国产精品免费视频一区| 无码人妻精品一区二区三区蜜桃| 国产成人无码精品一区不卡| 亚洲av无码天堂一区二区三区 | 一区二区三区www| 国产麻豆媒一区一区二区三区 | 一区二区三区四区在线播放| 日韩AV无码一区二区三区不卡| 中文字幕日韩一区| 日韩国产免费一区二区三区| 精品国产一区二区三区四区| 怡红院一区二区在线观看| 亚洲视频在线一区| 日韩一区二区电影| 波多野结衣的AV一区二区三区| 中文乱码人妻系列一区二区| 亚洲熟妇av一区二区三区下载| 无码一区二区三区| 在线视频一区二区| 成人一区二区三区视频在线观看| 亚洲第一区香蕉_国产a| 搡老熟女老女人一区二区|