Alvis Wu
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # JDBC 小吳 20210423 ###### tags: `JDBC` # 模組1 - JDBC API簡介 ## ==JDBC API設計目的== ## 資料庫種類 - ==關聯式資料庫(Relational DataBase Management System)== 1. 以表格方式儲存與呈現資料,再用數學集合論為基礎,將表格之間建立關聯以處理複雜的資料關係 2. 如Oracle Database, MySQL, 微軟SQL Server, IBM的DB2等 <br> - ==非關聯式資料庫(又稱NoSQL)== 1. 分散式進行資料儲存,可區分三大類:文檔儲存、圖形關係儲存與鍵值儲存(key – value) 2. 如Google的BigTable, MongoDB, Cassandra, Redis等 <br> --- ## 程式與資料庫通訊(1) - 資料庫本身是一個獨立運行的應用程式,所以我們設計的應用程式得利用 ==網路通訊協定== 對資料庫進行指令交換,以便進行資料的CRUD ==(增刪改查)== ![](https://i.imgur.com/kEs6a42.png) <br> - 但實作上我們會使用一組專門與資料庫進行通訊協定的類別庫來簡化與資料庫溝通的程式撰寫 ![](https://i.imgur.com/YHH50VI.png) <br> --- ## 程式與資料庫通訊(2) - 問題: 1. 不同廠商資料庫的通訊協定都不一樣,需使用不同類別庫撰寫程式 2. 遇到更換資料庫,程式碼也幾乎跟著要重寫 3. 應用程式被類別庫綁死,跨平台議題考量(?) <br> - 解決: ![](https://i.imgur.com/yw25fJQ.png) <br> --- ## ==JDBC API與關聯式資料庫== ## 資料庫種類 - Java提供一組++資料庫存取API++,名為JDBC ==(Java DataBase Connectivity)== ##### 備註 JDBC是搭配關聯式資料庫的API <br> - JDBC是 ==用於執行SQL的解決方案==,Java應用程式開發人員使用JDBC的標準介面,而資料庫廠商則對介面進行實作。因此應用程式開發人員就不需接觸到底層資料庫的驅動程式 - JDBC API使得應用系統開發者能使用相同的介面名稱與方法來存取資料庫的資料,讓程式設計師能專心於應用系統的開發,無需顧慮到不同廠商所提供的不同資料庫系統 ![](https://i.imgur.com/3oK7Z3x.png) <br> <br> --- ## ==java.sql套件== ## JDBC API套件 - JDBC API已包含在JDK裡 1. ==java.sql==:JDBC的核心API,用來存取資料庫資料,基本功能 2. ==javax.sql==:JDBC Extension API,支援進階資料庫存取功能 <br> - JDBC標準API分為兩個部份 1. JDBC應用程式開發者介面 (Application Developer Interface) 2. JDBC驅動程式開發者介面 (Driver Developer Interface) ##### 備註 驅動程式為資料庫廠商實作,一般開發者無須瞭解 <br> --- ## java.sql 示意圖 ![](https://i.imgur.com/2iiANFt.png) <br> --- # 模組2 - JDBC Driver ## ==JDBC Driver作用== ## JDBC Driver ![](https://i.imgur.com/IN7zsJt.png) ##### 備註 分層架構設計目的就是為了降低相依性 <br> --- ## ==四種JDBC Driver== ## Type 1 Driver - JDBC-ODBC Bridge Driver: 為JDK安裝即附,將JDBC的運作轉成ODBC的機制來連接資料庫,存取速度與功能均有受限,彈性不足,建議在無其它driver可以使用時才用Type1的driver ![](https://i.imgur.com/uHnRRgV.png) ##### 備註 JDK 8已將ODBC相關類別庫移除 <br> --- ## Type 2 Driver - Native API Driver : 此類型driver會以 ==原生(Native)== 方式呼叫資料庫提供的原生程式庫(通常是C/C++實作),因為採用原生方式,++故存取速度較Type1快++,==但沒有達到跨平台的目標==,需要在各平台先行安裝資料庫所屬的原生程式庫 ![](https://i.imgur.com/e1aP5d3.png) <br> --- ## Type 3 Driver - JDBC-Net Driver: 此類型driver會將JDBC呼叫轉換為特定的網路協定(Protocol),由中介伺服器或元件跟資料庫進行操作,使用此類型driver的==好處是軟體架構可獲得彈性,但速度會較慢== ![](https://i.imgur.com/ZEAkwFC.png) <br> --- ## Type 4 Driver - Native Protocol Driver: 此類型driver通常由資料庫廠商直接提供,會將JDBC呼叫轉換為與資料庫特定的網路協定,driver可完全用Java技術實現,因此==達到跨平台功能,效能也有不錯表現,為業界最常見的driver類型== ![](https://i.imgur.com/iJAOZuQ.png) <br> --- ## 下載與設定JDBC Driver - JDBC Driver可以從各資料庫網站下載並取得,基本上都是免費取得,而Type 4 Driver通常都是以JAR檔的形式打包好提供給程式設計師們使用 - 在Eclipse的Java Project裡,需要將JAR引入給專案才能使用,但通常會再建議將下載到的JAR檔放置於我們自行設定的classpath下,這樣就能獨立環境也能正常運作 - Eclipse的Java Project引入JAR檔可參考以下圖文操作說明: <br> ![](https://i.imgur.com/cZsAwFF.png) <br> ![](https://i.imgur.com/Ld3wC3u.png) <br> ![](https://i.imgur.com/lry4LcT.png) <br> --- # 模組3 - JDBC Driver註冊 ## ==JDBC Driver三種註冊== ## 載入JDBC Driver - 載入JDBC Driver有 ==(3+1)== 種方式: 1. Class Loader方式 - ++類別載入器++ ==(常用)== 2. register方式 - ++會產生共兩個驅動物件,可能會導致資源釋放的問題++ ==(不要用!!!)== 3. System Property方式 - ++看情況,若是同時要註冊多種驅動就可以用此方法++ <br> - 採用 ++Class Loader++ 方式 ==產生Driver實體==,並++註冊到DriverManager的驅動程式註冊表單++中 - Class.forName(“com.mysql.jdbc.Driver”); - ==Class.forName(“com.mysql.cj.jdbc.Driver”); (MySQL 8以後的驅動名稱)== - Class.forName(“oracle.jdbc.driver.OracleDriver”); - Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”); - Class.forName(“com.ibm.db2.jdbc.app.DB2Driver”); ##### 備註 "forName"傳入要載入的類別長名稱(套件+類別名) <br> - 採用register方式產生Driver實體,並將自己註冊到Driver Manager驅動程式註冊表單中 - DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); - DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); ![](https://i.imgur.com/CTdtdxk.png) <br> <br> - 採用System Property方式 - System.setProperty(“jdbc.drivers”, “com.mysql.jdbc.Driver”); - 可以包含數個drivers,彼此之間以冒號(:)隔開 - ex: ![](https://i.imgur.com/F8prD0Q.png) <br> --- ## ==Class Loader== ## 類別載入器 (Class Loader) - Java在執行時,需要某類別才會載入.class檔案,而非在程式啟動就載入所有類別,才能讓系統資源的運用更有效率。而載入.class檔案,就會產生一個java.lang.Class的物件實體來對應該檔案,程式設計師即可利用該Class物件實體而更進一步地取得該類別的相關資訊,此機制就稱為 ==反射或映射(Reflection)== - 需要某類別的時機: 1. 使用指定類別要產生物件實體時 (static區塊會執行) 2. 使用`Class.forName()`方法 3. 使用ClassLoader的`loadClass()`方法 (static區塊不執行) - JDK 8以前類別載入器可分為三個層級: Bootstrap Loader → ExtClassLoader → AppClassLoader ==(對應基礎 java模組28的類別路徑)== <br> --- ## ==自動載入JDBC Driver (JDBC 4.0)== - 在JDBC 4.0,也就是對應到Java SE6,增加了簡化資料庫驅動載入 - 不需用再呼叫Class.forName方法載入驅動,但在包裝JDBC驅動程式的JAR檔裡,必須要額外有一個「META-INF/services/java.sql.Driver」的檔案 - 該檔案裡要有註明驅動程式的類別名稱,才能達到簡化載入的操作 ##### 備註 須注意Java、JDBC版本和驅動程式版本是否有支援 <br> --- # 模組4 - 建立與關閉資料庫連線 ## ==建立資料庫連線== ## 資料庫位置 (URL) - 資料庫URL為一字串,用以說明連接某一特定資料庫所需要的資訊,包含資料庫位址(IP)、埠號(Port Number)、名稱等 - 資料庫URL格式: ==jdbc : <Subprotocol> : <Subname>== - 範例: “jdbc:mysql://” + serverName + “:3306/” + Schema Name → jdbc:mysql://localhost:3306/HR ==?serverTimezone=Asia/Taipei== MySQL 8.0 以後須在URL後面加上 ==時區設定== 才能正常連接 <br> ``` - “jdbc:oracle:thin:@” + serverName + “:1521” + SID → jdbc:oracle:thin:@localhost:1521:xe (xe指的是Oracle的Express版) ``` ``` - “jdbc:sqlserver://” + serverName + “:1433:databaseName=” + DBName → jdbc:sqlserver://localhost:1433:databaseName=HR ``` <br> ##### 備註 埠號: 1. 只要有網路通訊就一定會使用到 2. 範圍從0~65535(共65536個) 3. 範圍從0~1024不使用,因為已經有相關的協定佔用了 <br> --- ## Connection - Connection代表資料庫一個連線通路,傳遞一系列的SQL指令給資料庫,並管理這些指令的認可與中止 - ==Connection con = DriverManager.getConnection(String url, String userID, String password);== 1. 以資料庫URL做為引數產生Connection物件來連接資料庫 2. DriverManager在驅動程式註冊表單搜尋driver,一旦driver認得此url,便會依據url的資訊連接資料庫 - ==Connection非常珍貴,使用完畢後務必完成歸還的動作!== <br> --- ## ==關閉資料庫連線== ## 關閉連線 – close( ) - close( ):歸還資源 1. Connection是極為重要的資源,建議寫在finally{ }裡 2. 範例: ``` finally { if (con != null) { try { con.close(); } catch (SQLException e) {…} } } ``` <br> - ==對con檢查不為null== 是為了避免連線尚未建立前就發生例外,導致例外訊息再堆疊NullPointerException訊息而增加除錯時的複雜度 <br> --- ## ==AutoCloseable介面== ## try-with-resources - 以往程式設計師需自行關閉資源,Java 7開始try – with – resources可確保物件(資源)最後一定會關閉 - 實作 ==java.lang.AutoCloseable== 與 ==java.io.Closeable== 介面的物件皆可視為資源 - 若將有實作AutoCloseable介面的物件置於try{ }裡,try{ }結束時,Java即會自動將該物件close - JDK 7裡,Connection介面 extends AutoCloseable介面 - 由於仍有可能使用JDK 7以前的版本,故還是寫在finally{ }較保險 <br> --- # 模組5 - 靜態SQL指令 – Statement ## ==Statement介面== - 藉由Connection的方法: ==Statement createStatement( )== 來建立與取得Statement物件 - 藉由++Statement++物件,才能==執行靜態的SQL指令==並與資料庫交談 - 因為是從Connection產生出來,所以在使用完畢時也得記得歸還資源:close()方法 - 請注意資源歸還順序: ==越晚建立,越早歸還== <br> --- ## ==更新與查詢指令== ## 執行SQL指令 - 執行SQL指令的主要兩個方法 1. ==ResultSet executeQuery(String sql)==:查詢資料庫,傳回ResultSet - 用於SQL的SELECT指令 2. ==int executeUpdate(String sql)==:更新資料庫,傳回成功更新的筆數 - 用於SQL的INSERT、UPDATE與DELETE指令 - SQL指令在程式碼裡是宣告為字串型別,並在呼叫execute相關方法時做為參數傳入,即可送出給資料庫達到交談目的 <br> --- # 模組6 - ResultSet介面 ## ==ResultSet游標機制== ## ResultSet介面 - 當執行`executeQuery()`方法,該方法即傳回從資料庫查詢的結果資料列 - 例如 SELECT * FROM EMPLOYEE後,可得到表格結構的結果 ![](https://i.imgur.com/F1pj0cU.png) <br> --- ## ==移動游標操作== ## 移動資料列游標 - 移動資料列游標的相關方法: 1. `next()`、`previous()`、`first()`、`last()`、`beforeFirst()`、`afterLast()` 2. `next()`傳回boolean值 3. true代表游標停留位置有指向一個資料列,false即代表沒有指向資料列 - 測試目前資料列指標位置的方法: `isFirst()`、`isLast()`、`isBeforeFirst()`、`isAfterLast()` ##### 備註 部份移動游標方法為JDBC 2.0時新增,需在建立Statement時設定! <br> --- ## ==使用游標取得欄位資料== ## 移動資料列游標 - 取出查詢結果資料欄的方法: 1. 有 `type getType(int columnIndex)` 或 `type getType(String columnName)` - ==index從1開始==,一般來說使用index較有效率 - 但要小心查詢++欄位的順序關係++ (Select *: 根據當初建立表格所宣告的欄位順序) 2. 其餘參考方法: `getBoolean()` `getByte()` `getShort()` `getInt()` `getLong()` `getFloat()` `getDouble()` `getString()` `getDate()` `getTime()` `getTimestamp()` `getBinaryStream()` - 其它方法: `int getRow()`:取得目前的列編號,若傳回0,表示游標不在任一列上,可能在第一列前或最後一列後 <br> --- # 模組7 - 動態SQL指令 – PreparedStatement ## ==串接組成動態SQL指令== ## SQL指令參數動態改變 - 試想系統操作時,每次要新增的資料或是要查詢資料的條件不會永遠都是相同的,但Statement物件只能讓我們執行靜態(也就是固定不變)的SQL指令。 - 因為++SQL指令在Java裡宣告為String++,所以剛好 ==結合變數與文字串接功能==,就可以達到SQL指令參數可隨著程式執行而動態改變 - 範例: ![](https://i.imgur.com/buIhobC.png) <br> --- ## ==SQL Injection== (SQL 注入攻擊) - 若是剛剛使用者輸入userName與userPassward為’ 1 OR ‘1’ = ‘1,會發生什麼事情呢? - 答案:(NAME = '1' OR '1'='1') and (PASSWORD = '1' OR '1'=‘1’) -> 結果為true,條件成立 - 以上情況,輸入文字夾帶SQL指令內容,若是未做檢查處理,很有可能就被組合成一個 ==合法且有意義的SQL指令==,讓資料庫做出完全不一樣的任務,造成被有心人士入侵或是破壞 <br> --- ## ==PreparedStatement介面== ## 預先處理的PreparedStatement - PreparedStatement為++Statement的子介面++,因此也可以執行SQL指令 - 藉由Connection的方法: `PreparedStatement prepareStatement(String sql)` 資料庫可預先編譯SQL指令,執行效能較快,常用於需變數傳遞且重複執行的SQL指令 - 因為是從Connection產生出來,所以在使用完畢時也得記得歸還資源: ==`close()方法`== <br> --- # 模組8 - 動態SQL指令運用 ## ==PreparedStatment== - 資料庫會將SQL指令預先編譯,可避免資料庫重複解析同一個SQL指令,執行效能較好,==因為可以動態處理SQL指令,可避免SQL Injection攻擊== <br> - 對SQL指令裡,++未知或是需動態改變的參數設定為++ =="?"==,並在每次++執行前++,對 =="?"== ++置入不同的值++,透過 `setType(int idx, Type value)` ++提供參數值++ -> ==? 的索引值也是從1開始== <br> - PreparedStatement執行動態SQL指令的兩個方法 1. `ResultSet executeQuery()` 2. `int executeUpdate()` ##### 備註 上述兩個()內沒有參數,因為SQL指令已經預先交給資料庫了 <br> --- # 模組9 - 預存程序(CallableStatement) ## ==預存程序相關== ## CallableStatement - ++繼承PreparedStatement介面++,所以也有++動態參數功能++ ==(搭配 “?”)== - `CallableStatement prepareCall(String sql)`:使用 ==預存程序(stored procedure)==,預存程序已事先內建在資料庫中,通常比預先編譯的效能佳 - 預存程序(stored procedure)在應用程式執行前,已事先編譯好在資料庫裡,因此++預存程序的效能一般比預先編譯的敘述快++ - ==程式設計師只需知道預存程序的名稱與輸入輸出的參數,無需暸解SQL指令== - 不同的資料庫有不同的預存程序語法;對三階開發人員來說,意義不大 ##### 備註 Statement的3種執行方法: 1.executeUpdate() 2.executeQuery() 3.execute(): 執行"未知"的SQL指令,例如-預存程序

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully