Faire de la variable qui stocke l'ID un type d'ID au lieu de int / long (Java)

Aperçu

Lorsqu'il porte un identifiant, il est généralement stocké dans int, long, String, etc., mais si tel est le cas, il peut devenir confus et difficile à comprendre dans les cas suivants.

public someMethod(int hogeId, int fugaId) { ... }

Si vous pouvez faire cela, vous pouvez éviter les erreurs imprudentes. (Si vous le faites chiguhagu, l'IDE vous le dira comme une erreur.)

public someMethod(HogeId hogeId, FugaId fugaId) { ... }

Point d'attention

Bien que cela soit plus facile à comprendre, il y a quelques points à prendre en compte.

  1. Jackson peut convertir de / vers JSON
  2. Ce qui peut être traité comme paramètre / résultat dans MyBatis
  3. Peut être traité comme un paramètre URL de Spring MVC ou une valeur de retour de @ RestController
  4. Étant donné que de nombreuses classes Id seront créées, il n'y a pas besoin d'une description gênante individuellement (faites en sorte que la classe parent l'implémente).
  5. Les performances ne sont pas compromises

Conclusion

Il peut être réalisé de la manière suivante.

PiyoId.java


package your.package;

import your.package.LongId;
import lombok.EqualsAndHashCode;

@EqualsAndHashCode(callSuper = true)
class PiyoId extends LongId {
    public PiyoId(String id) { super(id); }
    public PiyoId(long id) { super(id); }
}

LongId.java


package your.package;

import com.fasterxml.jackson.annotation.JsonValue;
import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public abstract class LongId {
    private final long id;

    public LongId(String id) {
        this.id = Long.parseLong(id);
    }

    public LongIdBase(long id) {
        this.id = id;
    }

    @JsonValue
    public long getId() {
        return this.id;
    }

    public String toString() {
        return this.getClass().getSimpleName() + "(" + this.id + ")";
    }
}

LongIdTypeHandler.java


package your.package;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import your.package.HogeId;
import your.package.LongId;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

//Liste des classes d'identification ici
@MappedTypes(value = {HogeId.class})
public class LongIdTypeHandler<E extends LongId> extends BaseTypeHandler<E> {
    private final Class<E> type;

    public LongIdTypeHandler(Class<E> type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
    }

    private E createInstance(boolean wasNull, long id) {
        if (wasNull) {
            return null;
        }
        try {
            return type.getDeclaredConstructor(long.class).newInstance(id);
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int num, E parameter, JdbcType jdbcType) throws SQLException {
        long id = rs.getLong(columnName);
        return createInstance(rs.wasNull(), id);
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        long id = rs.getLong(columnName);
        return createInstance(rs.wasNull(), id);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        long id = rs.getLong(columnIndex);
        return createInstance(rs.wasNull(), id);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        long id = cs.getLong(columnIndex);
        return createInstance(cs.wasNull(), id);
    }
}

Détails

Compatible Jackson

Pour pouvoir effectuer une conversion de manière transparente, il doit s'agir de l'un des éléments suivants:

Conversion en JSON-> Objet

L'un des éléments suivants:

  1. Constructeur par défaut + setters
  2. Constructeur avec @ JsonCreator
  3. Constructeur avec arguments correspondants

Objet-> Convertir en JSON

L'un des éléments suivants: 4. Jugement des getters 5. Exécutez la méthode avec @ JsonValue

Conclusion

Correspond à 3 et 5

Prend en charge MyBatis

L'objet peut maintenant être passé en tant que paramètre MyBatis

Les deux problèmes suivants doivent être abordés:

1. Si la classe ID est un paramètre

--Je veux spécifier parameterType =" com. ~ .PiyoId " et le récupérer avec la description# {id}.

2. Lors de la réception d'une classe qui caractérise la classe ID comme argument

Cela ne fonctionne pas avec selectKey


<insert id="insert" parameterType="your.package.Hoge">
  INSERT INTO hoges (value1, value2)
  VALUES (#{value1}, #{value2})
  <selectKey resultType="your.package.HogeId" keyProperty="id" order="AFTER">
    select @@IDENTITY
  </selectKey>
</insert>

UseGeneratedKeys fonctionne


<insert id="insert" parameterType="your.package.Hoge" useGeneratedKeys="true" keyProperty="id">
  INSERT INTO hoges (value1, value2)
  VALUES (#{value1}, #{value2})
</insert>

Compatible avec les ressorts

Paramètres Spring MVC Controller

--Dans l'un des cas suivants, je souhaite recevoir un paramètre avec une valeur numérique telle que 123 en tant que type PiyoId. -- @ PathVariable ("piyoId") PiyoId piyoId --Lors de la réception en tant que @RequestBody PiyoForm form ou @ModelAttribute PiyoForm form, et lors de la réception en tant que PiyoId type in form

Valeur de retour Spring MVC @ RestController

--Si PiyoId est mélangé, je veux le convertir en JSON en tant que valeur numérique. --Conclusion: ce n'est pas grave s'il prend en charge Jackson mentionné ci-dessus.

Les performances ne sont pas compromises

code de vérification


//Écrivez plus tard

Recommended Posts

Faire de la variable qui stocke l'ID un type d'ID au lieu de int / long (Java)
Comparer les éléments d'un tableau (Java)
[Java] Comment convertir un élément d'un tableau de type String en type Int
[Java] Faites attention au type de clé de la carte
Veuillez noter la division (division) de java kotlin Int et Int
Un programme (Java) qui génère la somme des nombres pairs et impairs dans un tableau
(Ruby on Rails6) Affichage de la base de données qui a obtenu l'identifiant de la base de données
[Java] [Java EE] [Glassfish] (suite) Style qui met en doute le cache de Glassfish
Initialisation avec une chaîne vide vers une instance de type Java String
[Java] Pour connaître les informations de type des paramètres de type à l'exécution
[Java] Différence entre l’affectation d’une variable de type de base et l’affectation d’une variable de type de référence