成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[Java][數(shù)據(jù)庫(kù)工具][坑] Juice README

CoXie / 1758人閱讀

摘要:注意供應(yīng)器只會(huì)在倉(cāng)庫(kù)工廠第一次創(chuàng)建工廠時(shí)調(diào)用,而參數(shù)處理器和結(jié)果解析器將在每次倉(cāng)庫(kù)方法被調(diào)用時(shí)調(diào)用。解析器接收一個(gè)語(yǔ)句表模型的類聲明觸發(fā)解析器的倉(cāng)庫(kù)方法聲明。因此當(dāng)您配置了一個(gè)結(jié)果解析器,語(yǔ)句的執(zhí)行時(shí)機(jī)將推遲到這里。

Juice

這是我自己做的一個(gè)小項(xiàng)目,也可能會(huì)棄坑... 留作紀(jì)念吧。GitHub 地址

簡(jiǎn)介

Juice 是一個(gè)簡(jiǎn)易的、尚不完善的基于 JavaSQL數(shù)據(jù)庫(kù)工具,它提供了對(duì)SQL語(yǔ)句最大程度的控制,和一點(diǎn)簡(jiǎn)單的擴(kuò)展能力。

這些是開(kāi)發(fā)時(shí)的一點(diǎn)筆記:
做個(gè)數(shù)據(jù)庫(kù)幫助庫(kù)雛形
做個(gè)數(shù)據(jù)庫(kù)幫助庫(kù)雛形2

使用效果
RepositoryFactory factory = RepositoryFactory.configure(ConnectionConfiguration.builder()
                .driverClass("com.mysql.jdbc.Driver")
                .connectionURL("jdbc:mysql://localhost:3306/hsc")
                .username("gdpi")
                .password("gdpi")
                .build());

StudentRepository repository = factory.get(StudentRepository.class);

List studentList = repository.findAll();
// LinkedList size: 56

Student student = repository.getNameById("20152203300");
// {name: "krun", id: null, college: null, ...}

int count = repository.updateGenderById("20152203300", "男");
// 1

Student student2 = repository.findById("20152203300");
// {name: "krun", id: "20152203300", gender: "男",  major: "軟件技術(shù)", ...}
功能與使用

使用 Juice 只需要簡(jiǎn)單的幾步:

注: 本示例使用 lombokmysql-connector(5.1.44)

數(shù)據(jù)庫(kù)連接配置: ConnectionConfiguration

當(dāng)前版本的 Juice 只需要以下幾個(gè)參數(shù)用以連接數(shù)據(jù)庫(kù):

driverClass:這個(gè)參數(shù)用于向驅(qū)動(dòng)管理器注冊(cè)一個(gè)數(shù)據(jù)庫(kù)連接驅(qū)動(dòng)。(本示例將使用 com.mysql.jdbc.Driver)

connectionURL: 這個(gè)參數(shù)用于向驅(qū)動(dòng)管理器獲取一個(gè)數(shù)據(jù)庫(kù)連接,常用的如:jdbc:mysql://localhost:3306/juice,您可以附帶任何連接語(yǔ)句中允許附加的參數(shù),如字符編碼設(shè)置等等。

username: 這個(gè)參數(shù)是獲取數(shù)據(jù)庫(kù)連接時(shí)所需要的數(shù)據(jù)庫(kù)賬戶名

password: 這個(gè)參數(shù)是獲取數(shù)據(jù)庫(kù)連接時(shí)所需要的數(shù)據(jù)庫(kù)密碼

不建議直接在 connectionURL中配置連接所需的數(shù)據(jù)庫(kù)賬戶及密碼。

在未來(lái)的版本中,Juice會(huì)嘗試加入對(duì) *.properties文件的支持,如此一來(lái),您可以直接在 *.properties文件中設(shè)置連接的詳細(xì)參數(shù)。對(duì)MySQL適用的 properties選項(xiàng)請(qǐng)參見(jiàn)這里。

在 Java SE 環(huán)境中,您可以通過(guò) ConnectionConfiguration.builder()構(gòu)造器來(lái)構(gòu)造一個(gè)配置:

ConnecetionConfiguration conf = ConnectionConfiguration.builder()
                                      .driverClass("com.mysql.jdbc.Driver")
                                      .connectionURL("jdbc:mysql://localhost:3306/juice")
                                      .username("gdpi")
                                      .password("gdpi")
                                      .build();

如果是類似 Spring 這樣可以配置 Bean實(shí)例的環(huán)境中,您可以使用類似如下的方式來(lái)以Bean的方式創(chuàng)建一個(gè)配置:

 
     
     
     
     
倉(cāng)庫(kù)工廠: RepositoryFactory

倉(cāng)庫(kù)工廠是創(chuàng)建、管理倉(cāng)庫(kù)的地方。Juice 允許在一個(gè) Java Application 中存在多個(gè)倉(cāng)庫(kù)工廠的實(shí)例,但由于每個(gè)倉(cāng)庫(kù)工廠都會(huì)持有一個(gè) 數(shù)據(jù)庫(kù)連接供應(yīng)器(ConnectionProvider) ,因此建議使用默認(rèn)全局工廠。

每個(gè)工廠都由一個(gè)自己的名字,默認(rèn)全局工廠的名字為: global, 這并不是一個(gè)常量值,為了避免某些情況下發(fā)生沖突,Juice 允許你在創(chuàng)建前修改 RepositoryFactory.FACTORY_GLOBAL 的值來(lái)更改默認(rèn)全局工廠的名字。請(qǐng)注意,如果您在創(chuàng)建全局工廠后修改了該值,那么再次使用 不指定名稱的工廠獲取方法(RepositoryFactory.get())將導(dǎo)致重新創(chuàng)建一個(gè)以新值命名的全局工廠。

在使用倉(cāng)庫(kù)工廠前,需要傳入一個(gè) ConnectionConfiguration實(shí)例,使倉(cāng)庫(kù)工廠得以初始化內(nèi)部的數(shù)據(jù)庫(kù)連接供應(yīng)器。

在 Java SE 環(huán)境中,您可以通過(guò)下面的方式來(lái)配置倉(cāng)庫(kù)工廠:

//這里的 conf 即為前一節(jié)所創(chuàng)建的數(shù)據(jù)庫(kù)連接配置

// 配置全局倉(cāng)庫(kù)工廠
RepositoryFactory globalFactory = RepositoryFactory.configure(conf);

// 配置指定名稱的倉(cāng)庫(kù)工廠
RepositoryFactory fooFactory = RepositoryFactory.configure("foo", conf);

// 請(qǐng)注意,使用第二種方式配置工廠時(shí),使用默認(rèn)全局工廠名稱將拋出錯(cuò)誤,因?yàn)檫@會(huì)破壞 API 所劃分的全局、特定工廠的界限
RepositoryFactory wrongFactory = RepositoyFactory.configure(RepositoryFactory.FACTORY_GLOBAL, conf);
// > RuntimeException

如果是類似 Spring 這樣可以配置 Bean實(shí)例的環(huán)境中,您可以使用類似如下的方式來(lái)以Bean的方式創(chuàng)建倉(cāng)庫(kù)工廠:

 
     


 
      
     

在配置倉(cāng)庫(kù)工廠后,您可以通過(guò) RepositoryFactory.get()RepositoyFactory.get(name)來(lái)獲取全局或給定名稱的倉(cāng)庫(kù)工廠。

表模型

Juice 可以將您給定的一個(gè) Java 類視為一個(gè)表模型,就像下面這樣:

@Data
@Entity("student")
public class Student {

   private String id;

   @Column("class")
   private String clazz;

   private int code;
   private String college;
   private String gender;
   private int grade;
   private String major;
   private String name;

}

@Data 注解來(lái)自 lombok

@Entity 注解是一個(gè)可選項(xiàng),它只有一個(gè)必填屬性: value。當(dāng)配置該注解時(shí),Juice將使用該值作為表名;如果您指定了這個(gè)類是個(gè)表模型,Juice 卻找不到該注解時(shí),將使用類名的全小寫(xiě)形式作為表名。

@Column注解同樣是一個(gè)可選項(xiàng),它只有一個(gè)必填屬性: value。當(dāng)配置該注解時(shí),Juice將使用該值作為數(shù)據(jù)庫(kù)中此表的字段名,否則使用 Java 類字段名作為數(shù)據(jù)庫(kù)中此表的字段名。

倉(cāng)庫(kù): Repository

Repository 是一個(gè)注解,它實(shí)際上只是一個(gè)用于表明某個(gè)接口是一個(gè)倉(cāng)庫(kù)的標(biāo)記。就像下面這樣:

public interface StudentRepository extends Repository {

    @Query (value = "SELECT * FROM %s")
    List findAll();

    @Query (value = "SELECT * FROM %s WHERE id = ?")
    Student findById(String id);

     @Query (value = "UPDATE %s SET gender = ? WHERE id = ?",
            processor = StudentChain.class,
            processMethod = "replaceParameterLocation")
     Integer updateGenderById(String id, String gender);

     @Query ("SELECT name FROM %s WHERE id = ?")
     Student getNameById(String id);

}

Repository需要填入兩個(gè)泛型信息,第一個(gè)是該倉(cāng)庫(kù)所操作的表模型,第二個(gè)是該表模型的主鍵類型。

注: 事實(shí)上到目前為止,Juice 并不區(qū)分主鍵和其他字段,只是為了以后完善留下空間。

@Query 注解

由于到目前為止,Juice 短期內(nèi)不會(huì)實(shí)現(xiàn) 解析方法名并映射為一個(gè)SQL操作 這個(gè) feature, 因此需要 @Query 注解來(lái)標(biāo)記一個(gè)方法,并以此提供一些信息,Juice 提供的擴(kuò)展能力也在這里體現(xiàn):

@Query注解具有以下七個(gè)屬性:

String value: 這個(gè)屬性指定了方法所映射的 SQL操作,其中有著一些約定:%s占位符用于 Juice 填充表名,而 ? 占位符是 PreparedStatement 所使用的參數(shù)占位符。由于 Juice 提供簡(jiǎn)單的默認(rèn)實(shí)現(xiàn),這些默認(rèn)實(shí)現(xiàn)使用的就是 PreparedStatement,因此如果您使用了不一樣的Statement實(shí)現(xiàn),您可以使用任何與之配合的占位符。注意:如果您選擇了使用 %*系列作為占位符,那么請(qǐng)記得第一個(gè) %s將會(huì)被 Juice 用來(lái)填充表名。

Class provider: 這個(gè)屬性指定了語(yǔ)句供應(yīng)器所處的類,您可以指定任何實(shí)現(xiàn)了RepositoryStatementProvider接口的類,默認(rèn)值為 Juiec 提供的DefaultPreparedStatementProvider,詳細(xì)信息請(qǐng)參見(jiàn)下文。

String provideMethod: 這個(gè)屬性指定了注解所在方法所使用的語(yǔ)句供應(yīng)器,當(dāng)provider 屬性使用默認(rèn)值時(shí),此屬性無(wú)效;默認(rèn)值為注解所在方法的名字或provide

Class processor: 這個(gè)屬性指定了參數(shù)處理器所處的類,您可以指定任何實(shí)現(xiàn)了 RepositoryParameterProcessor接口的類,默認(rèn)值為 Juiec 提供的默認(rèn)參數(shù)處理器 DefaultParameterProcessor,詳細(xì)信息請(qǐng)參見(jiàn)下文。

String processMethod: 這個(gè)屬性指定了注解所在方法所使用的參數(shù)處理器,當(dāng)processor屬性使用默認(rèn)值時(shí),此屬性無(wú)效;默認(rèn)值為注解所在方法的名字或 process。

Class resolver: 這個(gè)屬性指定了結(jié)果解析器所處的類,您可以指定任何實(shí)現(xiàn)了 RepositoryResultResolver接口的類,默認(rèn)值為 Juiec 提供的 DefaultResultResolver,詳細(xì)信息請(qǐng)參見(jiàn)下文。

String resolveMethod: 這個(gè)屬性指定了注解所在方法所使用的結(jié)果解析器,當(dāng)resolver屬性使用默認(rèn)值時(shí),此屬性無(wú)效;默認(rèn)值為注解所在方法的名字或 resolve。

注意

您所指定的 provideMethod、processMethod、resolveMethod都必須是靜態(tài)方法,這并無(wú)太多考量,只是為了減輕 Juice 的對(duì)象管理成本。

語(yǔ)句供應(yīng)器 RepositoryStatementProvider

一個(gè)語(yǔ)句供應(yīng)器的方法簽名應(yīng)該如下:

public static Statement provideMethodName(Connection connection, String sql)

供應(yīng)器所在的類是 @Query.provider 的值,方法名是 @Query.provideMethod 的值。

供應(yīng)器接收一個(gè) java.sql.connection@Query.value值,并返回一個(gè) java.sql.statement

這里的 sql 已經(jīng)填充了表名

這里的Connection可以不關(guān)閉,它會(huì)由倉(cāng)庫(kù)工廠進(jìn)行復(fù)用。

注意:供應(yīng)器只會(huì)在倉(cāng)庫(kù)工廠第一次創(chuàng)建工廠時(shí)調(diào)用,而參數(shù)處理器和結(jié)果解析器將在每次倉(cāng)庫(kù)方法被調(diào)用時(shí)調(diào)用。

如果您希望使用項(xiàng)目所特定的、實(shí)現(xiàn)了裝飾器模式的、特殊的Statement實(shí)例,可以為方法定義一個(gè)、或創(chuàng)建一個(gè)全局的語(yǔ)句供應(yīng)器,并為所有方法指定。

也許后期會(huì)在 factory 中加入替換默認(rèn)語(yǔ)句供應(yīng)器、參數(shù)處理器、結(jié)果解析器的接口。

默認(rèn)的語(yǔ)句供應(yīng)器 DefaultPreparedStatementProvider.provide將根據(jù)給定 sql創(chuàng)建一個(gè) com.mysql.jdbc.PreparedStatement實(shí)例。

參數(shù)處理器 RepositoryParameterProcessor

一個(gè)參數(shù)處理器的方法簽名應(yīng)該類似下面這樣(這里對(duì)應(yīng)的是 StudentRepository.findById):

public static Statement findById (Statement statement, String id)

處理器所在的類是 @Query.processor的值,方法名是 @Query.processMethod 的值。

處理器接收一個(gè)java.sql.statement和具體的參數(shù)列表,并返回一個(gè)java.sql.statement。

如果您希望在每次方法調(diào)用時(shí)都有個(gè)地方可以記錄日志、進(jìn)行參數(shù)檢查,可以為其配置一個(gè)參數(shù)處理器。

在當(dāng)前版本的 Juice 中,如果您希望處理類似下面這種情況:

public StudentRepository extends Repository {
  
  @Query("INSERT INTO %s (%s) VALUES (%s)")
  Integer insert(Student student);
  
}

您需要為其配置一個(gè)語(yǔ)句供應(yīng)器:

public static Statement insert(Connection connection, String sql) {
    return connection.prepareStatement(
      String.format(sql,
        StringUtils.convertObjectFields2StringList(Student.class)));
}

和一個(gè)參數(shù)處理器:

public static Statement insert(Statement statement, Student student) {
    PreparedStatement ps = (PreparedStatement) statement;
      for (Field field : student.getClass().getDeclaringFields()) {
      field.setAccessable(true);
      ps.setObject(index, field.get(student));
    }
}

以上均為偽代碼

Juice 所提供的默認(rèn)參數(shù)處理器 DefaultParameterProcessor,只是簡(jiǎn)單得把參數(shù)按順序填充入SQL語(yǔ)句中并返回。因此,類似下面這種情況可能會(huì)發(fā)生錯(cuò)誤:

public StudentRepository extends Repository {
    
  @Query("UPDATE %s SET gender = ? WHERE id = ?")
  Integer setGenderById(String id, String gender);
  
}

setGenderById的參數(shù)列表中,id在前,gender·在后,這會(huì)使得DefaultParameter.process輸出:

UPDATE student SET gender = {id} WHERE id = {gender}

顯然這是錯(cuò)誤的。如果要避免這種情況,可以直接把方法的參數(shù)列表按 SQL語(yǔ)句中的參數(shù)順序排放;也可以為其指定一個(gè)參數(shù)處理器用以調(diào)整參數(shù)填充順序。

結(jié)果解析器 RepositoryResultResolver

一個(gè)結(jié)果解析器的方法簽名應(yīng)該類似下面這樣:

public static Object resolve(Statement statement, Class entityClass, Method method)

解析器所在的類是 @Query.resolver 的值,方法名是@Query.resolveMethod的值。

解析器接收一個(gè)java.sql.statement語(yǔ)句、Class表模型的類聲明、Method觸發(fā)解析器的倉(cāng)庫(kù)方法聲明。

這里的 statement 尚未執(zhí)行,因?yàn)?b>java.sql.statement.execute系列接口需要一些額外參數(shù),這導(dǎo)致 Juice無(wú)法確保一致的行為。因此當(dāng)您配置了一個(gè)結(jié)果解析器,語(yǔ)句的執(zhí)行時(shí)機(jī)將推遲到這里。

Juice 所提供的默認(rèn)解析器 DefaultResultResolver有著很多限制:

只支持解析倉(cāng)庫(kù)所聲明的表模型類型和其List形式

對(duì)于 INSERT/UPDATE/DELETE操作,只會(huì)返回Integer數(shù)值用以表示該SQL操作影響的行數(shù)

不支持表模型字段含有其他非SQL types類型的遞歸、嵌套解析

因此,如果您希望能解析復(fù)雜的結(jié)果,例如將前一節(jié)中的 insert操作返回插入后的結(jié)果并映射為一個(gè)Student:

public StudentRepository extends Repository {
    
  @Query("UPDATE %s SET gender = ? WHERE id = ?")
  Student setGenderById(String id, String gender);
  
}

那么還需要配置一個(gè)結(jié)果解析器:

public static Student insert(Statement statement, Class entityClass, Method method) {
    // 解析邏輯...
}
結(jié)束

那么, Juice 的介紹、使用幫助就到此結(jié)束了,感謝您的觀看 : )

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70572.html

相關(guān)文章

  • 如何寫(xiě)好技術(shù)簡(jiǎn)歷 —— 實(shí)例、模板及工具

    摘要:在線簡(jiǎn)歷生成工具,可以導(dǎo)出。技巧目前寫(xiě)簡(jiǎn)歷的方式有兩種普遍被認(rèn)可,一種是一種是。培養(yǎng)新人和帶團(tuán)隊(duì)其他項(xiàng)目項(xiàng)目該項(xiàng)目是,使用技術(shù),完成功能。閱讀原文點(diǎn)擊查看簡(jiǎn)歷模板。 工欲善其事必先利其器,這是自古以來(lái)的道理,所以如果想找到一份好的工作,一定要先整理一份好的簡(jiǎn)歷。 模板 寫(xiě)簡(jiǎn)歷首先要有一個(gè)好的模板,我們做技術(shù)的不同于 UX,UED,我們不需要那么花哨,但是也需要整潔干凈。好的模板能讓你的...

    sunnyxd 評(píng)論0 收藏0
  • ES6入門筆記(一)

    摘要:用聲明的常量無(wú)法在后面的代碼中改值。表達(dá)式里還有一個(gè)很方便的就是表達(dá)式,舉個(gè)例子運(yùn)行結(jié)果為后聲明的里以數(shù)組的形式存放了函數(shù)的剩余參數(shù),是不是很方便。 ES6入門筆記(一) 安裝babel 由于瀏覽器對(duì)ES6的支持還不是很好,編寫(xiě)ES6代碼前我們要安裝一個(gè)babel工具將ES6代碼編譯成ES5代碼,用如下命令安裝babel: npm install -g babel-core ...

    warkiz 評(píng)論0 收藏0
  • Java 8之stream實(shí)際應(yīng)用

    摘要:前言在前面的之介紹和使用和之進(jìn)階中講了的使用方式和一些常用的方法,這篇文章就來(lái)演示一下的實(shí)際應(yīng)用。實(shí)際應(yīng)用先創(chuàng)建一個(gè)訂單類和商品類,每個(gè)訂單都有年份商品數(shù)量和商品對(duì)象屬性,而商品類里面則包含了名字和價(jià)格屬性。 前言: 在前面的 Java 8之stream介紹和使用 和 Java 8之stream進(jìn)階 中講了stream的使用方式和一些常用的方法,這篇文章就來(lái)演示一下stream的實(shí)際應(yīng)...

    jonh_felix 評(píng)論0 收藏0
  • 設(shè)計(jì)模式(10)狀態(tài)模式(講解+應(yīng)用)

    摘要:狀態(tài)模式對(duì)于對(duì)象內(nèi)部的狀態(tài),允許其在不同的狀態(tài)下,擁有不同的行為,對(duì)狀態(tài)單獨(dú)封裝成類。通過(guò)什么來(lái)舉例子呢設(shè)計(jì)到多狀態(tài),不同狀態(tài)下各自具有不同行為的東西,而且理解起來(lái)相對(duì)容易的。下篇更新適配器模式 目錄 狀態(tài)模式 為什么使用狀態(tài)模式? 應(yīng)用實(shí)例 狀態(tài)模式 狀態(tài)模式,顧名思義,肯定是和狀態(tài)有關(guān),進(jìn)一步思考,我們?cè)谟懻摰氖窃O(shè)計(jì)模式,設(shè)計(jì)模式中的重要原則對(duì)變化的進(jìn)行封裝,順著這個(gè)思路去想,...

    lakeside 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

CoXie

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<