[JAVA] Prise en main des opérateurs logiques utilisant Doma tels que AND et OR dans la clause WHERE de l'API Criteria

introduction

Lors de la construction de la clause WHERE de SQL, pour spécifier plusieurs conditions, il est nécessaire de concaténer avec des opérateurs logiques tels que AND et OR. Cet article montre comment une telle concaténation d'opérateurs logiques peut être représentée par l'API Criteria dans Doma 2.43.0.

La concaténation d'opérateurs logiques est une fonction simple à exprimer en SQL, mais comment la réaliser en tant que langage de programmation est une question à considérer. La caractéristique de Doma est qu'elle peut être exprimée à l'aide d'une expression lambda.

Pour un aperçu de Doma et de l'API Criteria, lisez les autres articles dans Introduction à Doma.

Exemple de code utilisé dans cet article

La base de données n'a qu'une seule table d'employés qui représente les employés.

schema.sql


create table employee (
    id integer not null primary key,
    name varchar(255) not null,
    age integer not null, 
    version integer not null);

Préparez la classe Employé comme classe d'entité correspondant à la table Employé.

Employee.java


@Entity(metamodel = @Metamodel)
public class Employee {
  @Id
  public Integer id;
  public String name;
  public Integer age;
  @Version public Integer version;
}

Nous préparerons ʻEmployeeRepositoryet réécrirons la méthodeselect` de cette classe pour montrer quelques exemples.

public class EmployeeRepository {

  private final Entityql entityql;

  public EmployeeRepository(Config config) {
    this.entityql = new Entityql(config);
  }

  public List<Employee> select() {
    //Voici un exemple de code réécrit de différentes manières
  }
}

Opérateur logique AND implicite

Si vous listez les conditions de recherche (ʻeq (..., ...) ʻ dans cet exemple), elles sont implicitement concaténées par AND.

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      c.eq(e.id, 1);
      c.eq(e.name, "aaa");
      c.eq(e.age, 20);
    }).fetch();

Le SQL généré ressemble à ceci: (Ci-après, le SQL avec la valeur liée incorporée est affiché, mais en réalité, le SQL est émis en utilisant la variable de liaison ?.)

select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 and t0_.name = 'aaa' and t0_.age = 20

Opérateur logique ET explicite

Dans l'exemple précédent, la méthode correspondant à AND n'a pas été appelée, mais il est également possible d'appeler explicitement la méthode ʻand correspondant à AND comme suit. La méthode ʻand reçoit une expression lambda.

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      c.eq(e.id, 1);
      c.and(() -> c.eq(e.name, "aaa"));
      c.and(() -> c.eq(e.age, 20));
    }).fetch();

Le SQL généré sera le suivant, et le même SQL que dans l'exemple précédent sera généré (cependant, il existe des différences telles que la présence ou l'absence de parenthèses).

select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 and (t0_.name = 'aaa') and (t0_.age = 20)

OU opérateur logique

Pour concaténer par OR, appelez la méthode ʻor comme suit: La méthode ʻor reçoit une expression lambda.

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      c.eq(e.id, 1);
      c.or(() -> {
        c.eq(e.name, "aaa");
        c.eq(e.age, 20);
      });
    }).fetch();

Le SQL généré ressemble à ceci:

select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 or (t0_.name = 'aaa' and t0_.age = 20)

Fonction de suppression automatique des principaux ET et OU

Similaire à l'exemple précédent, mais quel type de SQL le code suivant génère-t-il?

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      c.or(() -> {
        c.eq(e.name, "aaa");
        c.eq(e.age, 20);
      });
      c.eq(e.id, 1);
    }).fetch();

Vous pourriez penser qu'un OR supplémentaire est généré immédiatement après la clause WHERE, mais Doma supprime automatiquement AND et OR au début de la clause WHERE, de sorte que le SQL suivant est généré.

select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where (t0_.name = 'aaa' and t0_.age = 20) and t0_.id = 1

Cette fonction est utile lorsque la nécessité de AND ou OR n'est pas déterminée statiquement en raison d'une branche conditionnelle dans la clause WHERE.

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      if (Une certaine condition) {
        c.or(() -> {
          c.eq(e.name, "aaa");
          c.eq(e.age, 20);
        });
      }
      if (Une certaine condition 2) {
        c.or(() -> {
          c.eq(e.name, "bbb");
          c.eq(e.age, 30);
        });
      }
    }).fetch();

Imbrication ET et OU

Vous pouvez imbriquer n'importe quel nombre de «et» et de «ou» sans aucune restriction.

    Employee_ e = new Employee_();
    return entityql.from(e).where(c -> {
      c.eq(e.id, 1);
      c.or(() -> {
        c.eq(e.name, "aaa");
        c.eq(e.age, 20);
        c.or(() -> {
          c.eq(e.name, "bbb");
          c.eq(e.age, 30);
        });
      });
    }).fetch();

Le code ci-dessus générera le SQL suivant:

select t0_.id, t0_.name, t0_.age, t0_.version from Employee t0_ where t0_.id = 1 or (t0_.name = 'aaa' and t0_.age = 20 or (t0_.name = 'bbb' and t0_.age = 30))

en conclusion

J'ai montré comment la concaténation d'opérateurs logiques peut être exprimée dans l'API Criteria de Doma.

Comme mentionné au début, l'API Criteira de Doma exprime la concaténation d'opérateurs logiques sous la forme d'une expression lambda. Il existe une chaîne de méthodes comme autre méthode d'expression, mais je pense personnellement que la chaîne de méthodes a une faiblesse. Il est vulnérable au branchement conditionnel. S'il y a une branche conditionnelle, la chaîne se brisera et la complexité augmentera aussitôt. En effet, vous devez stocker l'objet à enchaîner dans une variable afin de connecter la chaîne. D'un autre côté, la méthode utilisant une expression lambda telle que l'API Criteria de Doma est simple et hautement lisible car il n'y a pas de différence de style d'écriture selon que le branchement conditionnel est inclus ou non (simplement parce qu'il est entouré de blocs if). Je pense.

Recommended Posts

Prise en main des opérateurs logiques utilisant Doma tels que AND et OR dans la clause WHERE de l'API Criteria
Premiers pas avec les sous-requêtes utilisant Doma avec l'API Criteria
Premiers pas avec Doma-Dynamic Construction de clauses WHERE avec l'API Criteria
Premiers pas avec Doma-Using Projection avec l'API Criteira
Premiers pas avec Doma-Using Joins avec l'API Criteira
Premiers pas avec Doma - Introduction à l'API Criteria
Premiers pas avec Reactive Streams et l'API JDK 9 Flow
[jOOQ] Comment utiliser CASE WHEN dans la clause WHERE / AND / OR
Résumer les principaux points de démarrage avec JPA appris avec Hibernate
Examinons la signification de "stream" et "collect" dans l'API Stream de Java.
[Firestore] Extrayez la collection avec la condition where dans Ruby et supprimez l'enregistrement