Résumé de l'ORM "uroboroSQL" qui peut être utilisé dans le Java d'entreprise

Ceci est une introduction à la bibliothèque de persistance DB de Java "uroboroSQL", dans laquelle l'auteur lui-même est impliqué en tant que committer.

uroboroSQL

https://github.com/future-architect/uroborosql

introduction

Dans le développement de systèmes d'entreprise, il est encore souvent réalisé en Java et, en raison des caractéristiques du système, RDB est souvent utilisé.

L'attention se concentre sur des produits tels que Amazon Aurora et Cloud Spanner. Je pense que la raison pour laquelle ils se rassemblent est qu'ils ont la particularité de renverser le théorème CAP selon lequel ils veulent utiliser à la fois les transactions et SQL, bien qu'ils souhaitent étendre la base de données en parallèle et distribuée au fur et à mesure que les temps changent.

J'ai posté un article le 24 décembre de l'année dernière Essayez de charger CockroachDB la veille de Noël, et ce CockroachDB est aussi un tel idéal. La nécessité d'enseigner les avantages de NoSQL avec RDB est un rêve que les ingénieurs aspirent:

Histoire de Java et RDB

Les systèmes créés avec Java au début des années 2000 utilisaient souvent l'API JDBC telle quelle, mais après cela, des mappeurs OR (tels que Hibernate, iBatis (actuellement MyBatis) et S2Dao du projet Seaser) ORM) a été développé et est maintenant utilisé.

Après cela, JPA (Java Persistence API) 1.0 a été formulé en tant que framework de persistance standard Java en 2006, JPA 2.0 en 2009, JPA 2.1 en 2013 et Java SE peut également être utilisé, mais Java EE C'est une situation où elle continue d'évoluer avec l'EJB de.

Pour la dernière comparaison de bibliothèques, l'article Discussion sur Java Persistence Framework 2017 (1) est très utile (désolé). Cependant, le SQL uroboro que je vais vous présenter n'est pas inclus: cry :).

Qu'est-ce qu'uroboroSQL

uroboroSQL est l'une des bibliothèques de persistance DB en Java, et adopte fondamentalement une approche qui complète le manque de SQL avec Java plutôt que de générer du SQL à partir de Java.

Bien sûr, il est difficile d'écrire SQL un par un avec INSERT / UPDATE / DELETE d'un enregistrement, nous fournissons donc également une API en tant qu'ORM.

Fonction caractéristique

Équipé de la fonction REPL qui est pratique pendant le développement

Vous pouvez l'essayer immédiatement sans construire lors du développement avec 2Way-SQL.

asciicast

Rapport de couverture

Il est possible d'agréger les branches conditionnelles d'instructions SQL et d'effectuer des rapports de couverture.

Autres caractéristiques

article Prise en charge d'uroboro SQL
Licence MIT
Système OSS
latest v0.5 (2017/12)
Externalisation SQL
DSL ×
Java 8<=
Compatible Stream Lambda
Génération automatique d'entité
Correspondance avec la valeur de division ○ (L'énumérateur et la classe constante sont acceptables)
Appel de procédure stockée
Personnalisation de ResultSet
Oracle
DB2 -
MySQL
PostgreSQL
MariaDB -
MS-SQL
H2
Derby
Sybase -
SQLite
Dépendance commons-lang3,slf4,ognl,jline

exemple de code uroboroSQL

Maintenant, pour comprendre la bibliothèque, il est rapide de voir quel type d'implémentation il s'agira lors de son utilisation. Donc, j'ai rassemblé un échantillon d'implémentations fréquemment utilisées.

À propos, au moment de la rédaction de cet article, il peut être plus abondant que le document officiel: sweat_smile:

Relier

SqlConfig config = UroboroSQL.builder("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "sa").build();

transaction

try (SqlAgent agent = config.agent()) {
  agent.required(() -> {
    // insert/update/delete
  });
}

2way-SQL

department/select_department.sql


SELECT /* _SQL_ID_ */
    DEPT.DEPT_NO    AS  DEPT_NO
,   DEPT.DEPT_NAME  AS  DEPT_NAME
FROM
    DEPARTMENT  DEPT
WHERE
    1               =   1
/*IF SF.isNotEmpty(dept_no)*/
AND DEPT.DEPT_NO    =      /*dept_no*/1
/*END*/
/*IF SF.isNotEmpty(dept_name)*/
AND DEPT.DEPT_NAME  LIKE   '%' || /*dept_name*/'' || '%'
/*END*/

department/insert_department.sql


INSERT /* _SQL_ID_ */
INTO
    DEPARTMENT
(
    DEPT_NO
,   DEPT_NAME
) VALUES (
    /*dept_no*/1
,   /*dept_name*/'sample'
)

department/update_department.sql


UPDATE /* _SQL_ID_ */
    DEPARTMENT  DEPT
SET
    DEPT.DEPT_NAME      =   /*dept_name*/'sample'
    DEPT.LOCK_VERSION   =   DEPT.LOCK_VERSION   +   1
WHERE
    DEPT.DEPT_NO        =   /*dept_no*/1
AND DEPT.LOCK_VERSION   =   /*lock_version*/0

department/delete_department.sql


DELETE /* _SQL_ID_ */
FROM
    DEPARTMENT  DEPT
WHERE
    DEPT.DEPT_NO    =   /*dept_no*/1

Avec la même syntaxe que S2Dao etc., vous pouvez décrire les branches avec une notation de commentaire en SQL.

SÉLECTIONNER

try (SqlAgent agent = config.agent()) {
  List<Map<String, Object>> deptList =
    agent.query("department/select_department")
      .param("dept_name", "retail")
      .collect();
}

SELECT (acquisition de flux, type de carte)

try (SqlAgent agent = config.agent()) {
  Stream<Map<String, Object>> depts =
    agent.query("department/select_department")
      .param("dept_name", "retail")
      .stream();
}

SELECT (acquisition de flux, type de modèle)

try (SqlAgent agent = config.agent()) {
  Stream<Department> depts =
    agent.query("department/select_department")
      .param("dept_name", "retail")
      .stream(Department.class);
}

SELECT (Obtenir 1 élément, type de carte, exception si impossible)

try (SqlAgent agent = config.agent()) {
  Map<String, Object> dept =
    agent.query("department/select_department")
      .param("dept_no", 1001)
      .first();
}

SELECT (obtenir un, type de modèle, exception sinon obtenir)

try (SqlAgent agent = config.agent()) {
  Department dept =
    agent.query("department/select_department")
      .param("dept_no", 1001)
      .first(Department.class);
}

SELECT (obtenir 1 élément, type de carte, facultatif)

try (SqlAgent agent = config.agent()) {
  Map<String, Object> dept =
    agent.query("department/select_department")
      .param("dept_no", 1001)
      .findFirst()
      .orElse(null);
}

SELECT (Obtenez 1 article, type de modèle, facultatif)

try (SqlAgent agent = config.agent()) {
  Department dept =
    agent.query("department/select_department")
      .param("dept_no", 1001)
      .findFirst(Department.class)
      .orElse(null);
}

INSERT/UPDATE/DELETE

try (SqlAgent agent = config.agent()) {
  agent.required(() -> {
    // insert
    agent.update("department/insert_department")
      .param("dept_no", 1001)
      .param("dept_name", "sales")
      .count();
    // update
    agent.update("department/update_department")
      .param("dept_no", 1001)
      .param("dept_name", "HR")
      .count();
    // delete
    agent.update("department/delete_department")
      .param("dept_no", 1001)
      .count();
  });
}

INSERT / UPDATE / DELETE (exécution par lots)

List<Map<String, Object>> inputList = new ArrayList<>();
//Omission

try (SqlAgent agent = config.agent()) {
  agent.required(() -> {
    agent.batch("department/insert_department")
      .paramStream(inputList.stream())
      .count();
  });
}

Interface DAO

On suppose que vous disposez de la classe de modèle suivante.

@Table(name = "DEPARTMENT")
public class Department {
  private int deptNo;
  private String deptName;

  @Version
  private int lockVersion = 0;

  //Getter omis/setter
}

Le champ avec @Version est reconnu par uroboroSQL comme information de version pour le verrouillage optimiste, +1 dans la clause SET au moment de UPDATE, ajouté à la condition de recherche de la clause WHERE, et SQL est émis, et le nombre de mises à jour est de 0. Déclenche ʻOptimisticLockException`.

SELECT (recherche de clé primaire)

try (SqlAgent agent = config.agent()) {
  Department dept =
      agent.find(Department.class, 1001).orElse(null);
}

À partir de la version 0.5.0, seule la recherche par clé primaire de table unique est disponible dans l'interface DAO, mais dans la dernière mise à niveau de version, il sera possible de spécifier des conditions de recherche équivalentes à la clause WHERE dans une seule table.

INSERT

try (SqlAgent agent = config.agent()) {
  Department hrDept = new Department();
  hrDept.setDeptNo(1002);
  hrDept.setDeptName("HR");
  agent.insert(hrDept);
}

UPDATE

try (SqlAgent agent = config.agent()) {
  agent.required(() -> {
    Department dept =
        agent.find(Department.class, 1001).orElseThrow(Exception::new);
    dept.setDeptName("Human Resources");
    agent.update(dept);
  });
}

DELETE

try (SqlAgent agent = config.agent()) {
  agent.required(() -> {
    Department dept =
        agent.find(Department.class, 1001).orElseThrow(Exception::new);
    agent.delete(dept);
  });
}

Référence: documentation uroboroSQL, outils, exemples

--uroboroSQL document japonais - https://future-architect.github.io/uroborosql-doc/ --Introduction d'uroboroSQL (OSC2017 Nagoya) #oscnagoya - https://www.slideshare.net/KenichiHoshi1/uroborosql-osc2017-nagoya-oscnagoya --uroboroSQL générateur de source - https://github.com/shout-star/uroborosql-generator --uroboroSQL exemple d'application CLI - https://github.com/future-architect/uroborosql-sample --exemple d'application web uroboroSQL (avec Spring Boot) - https://github.com/shout-star/uroborosql-springboot-demo

Recommended Posts

Résumé de l'ORM "uroboroSQL" qui peut être utilisé dans le Java d'entreprise
Ecrire une classe qui peut être ordonnée en Java Un petit mémo standard
Extrait technologique pouvant être utilisé pour créer des sites EC dans la formation Java
Touches de raccourci pratiques pour Eclipse
Liste des appareils pouvant être prévisualisés avec Swift UI
Java (édition super débutante) compréhensible en 180 secondes
Ruby on Rails 5 guide pratique d'apprentissage rapide qui peut être utilisé sur le terrain Résumé
Syntaxe et conditions d'occurrence d'exception pouvant être utilisées lors de la comparaison avec null en Java
[Java 8] Méthode de tri par ordre alphabétique et par ordre de longueur de chaîne de caractères pouvant être utilisée dans les tests de codage
Un résumé concis des API de date / heure Java 8 susceptibles d'être utilisées fréquemment
Mémo de référence / serveur LDAP en mémoire pouvant être intégré à Java
Outil d'analyse statique pouvant être utilisé avec GitHub [version Java]
Notez que les propriétés système, y compris JAXBContext, ne peuvent pas être utilisées dans Java11
SwiftUI View qui peut être utilisé en combinaison avec d'autres frameworks
Résumé des JDK pouvant être installés avec Homebrew (à partir de novembre 2019)
Comment créer une paire de clés d'ecdsa dans un format lisible par Java
Traitement d'entrée / sortie de fichier Java pouvant être utilisé via l'historique
Résumé des bibliothèques qui semblent souvent utilisées dans le développement récent d'Android (2019/11)
[Android Studio] Description qui peut être saisie en continu dans la base de données SQLite [Java]
[Spring Boot] Liste des règles de validation qui peuvent être utilisées dans le fichier de propriétés pour les messages d'erreur
Organiser les méthodes qui peuvent être utilisées avec StringUtils
Interface fonctionnelle de base compréhensible en 3 minutes
L'histoire du port devenant inutilisable dans l'exemple de programme Spring Boot
Le traitement Java 8 Stream peut être omis jusqu'à présent!
Résumé personnel des types souvent utilisés dans JUnit 4
À propos du problème que hidden_field peut être utilisé de manière insensée
Résumé de la mise en œuvre des arguments par défaut en Java
Résumé du support Java 2018
[Spring Data JPA] La condition And peut-elle être utilisée dans la méthode de suppression implémentée automatiquement?
Introduction de jQuery-jusqu'à ce qu'il puisse être utilisé (enregistrement exécuté en préparation pour une communication asynchrone) haml
[Java] Il semble que `0 <hoge <10` ne puisse pas être écrit dans l'expression conditionnelle de l'instruction ʻif`.
Créer un contrôle de page qui peut être utilisé avec RecyclerView
Créez un fichier jar qui peut être exécuté sur Gradle
Le cas où @Autowired n'a pas pu être utilisé dans JUnit5
Base de données Firebase-Realtime sur Android pouvant être utilisée avec copie
Problèmes facilement confondus avec Java et JavaScript
[Question] Nullif peut-il être utilisé dans la fonction de comptage de JPQL?
Introduction à Rakefile qui peut être effectuée en 10 minutes environ
Éléments à prendre en compte lors de l'écriture de code en Java
Nouvelles fonctionnalités de Java 14 pouvant être utilisées pour écrire du code
Si les options peuvent être utilisées en raison des différentes versions de Java
[Java11] Résumé du flux -Avantages du flux-
[Java] Résumé des expressions régulières
[Java] Résumé des opérateurs (opérateur)
Résumé des bases du langage Java
Résumé de la classe Java Math
[Java] Résumé de la syntaxe de contrôle
Implémentation Java de tri-tree
Résumé du traitement des erreurs Java
[Java] Résumé des modèles de conception
[Java] Résumé des opérations mathématiques
Résumé de «Modèles de conception appris en langage Java (édition multithread)» (partie 10)
Résumé de «Modèles de conception appris en langage Java (édition multithread)» (partie 7)
Résumé de «Modèles de conception appris en langage Java (édition multithread)» (partie 3)
Résumé de «Modèles de conception appris en langage Java (édition multithread)» (partie 9)