Quantcast
Channel: Planeta Código
Viewing all articles
Browse latest Browse all 2732

Blog Bitix: Ventajas de usar un tipo específico para los identificadores de las entidades en vez de un tipo básico

$
0
0
Java
jOOQ

Al persistir una entidad de dominio en la base de datos su identificador se guarda como un tipo de datos soportado por la base de datos. Si es una base de datos relacional habitualmente es el equivalente a un bigint o en una base de datos de documentos quizá un UUID. En las entidades de dominio el tipo de datos usado para el identificador es el equivalente de la base de datos en el lenguaje de programación. Por ejemplo, si en una base de datos la clave primaria es un bigint el identificador en la entidad de dominio es un Long. Esto es lo mas simple pero tiene algún inconveniente.

El inconveniente es que al ser el identificador un tipo de datos básico cualquier Long es aceptado, con lo que se hacen posibles errores o malos comportamientos al usar un identificador de otra entidad de dominio si también es un Long donde no se debería. El compilador no captura este tipo de errores porque entiende como correcto cualquier Long independientemente de su significado desde el punto de vista de la aplicación.

También en cierta medida es un problema en la legibilidad del código ya que el tipo de dato de una variable no es significativo para saber si es un identificador. También es un problema al trabajar con colecciones, los siguientes ejemplos de código demuestran que los tipos no son todo lo semánticos o significativos que deberían.

1
2
Longid=...;List<Long>ids=...;

La solución es crear un tipo para cada identificador de cada entidad y en vez de usar un Long pasar a usar un ProductoId, UsuarioId, CompraId o como en el ejemplo EventId. Estas serían unas posibles implementaciones.

1
2
3
4
packageio.github.picodotdev.domain.misc;publicinterfaceEntityId{}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
packageio.github.picodotdev.domain.misc;publicabstractclassLongIdimplementsEntityId{privateLongvalue;publicLongId(Longvalue){this.value=value;}publicLonggetValue(){returnvalue;}}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
packageio.github.picodotdev.domain.event;importio.github.picodotdev.domain.misc.LongId;importjava.util.Objects;publicclassEventIdextendsLongId{publicEventId(Longid){super(id);}@OverridepublicinthashCode(){returnObjects.hashCode(getId());}@Overridepublicbooleanequals(Objecto){if(this==o){returntrue;}if(!(oinstanceofEventId)){returnfalse;}returnObjects.equals(getId(),((EventId)o).getId());}}

El tipo de las colecciones ahora son más semánticas además de que el compilador realizará comprobaciones de tipos.

1
2
EventIdid=...;List<EventId>ids=...;

En la popular herramienta ORM de persistencia Hibernate o JPA se puede usar el tipo propio para el identificador usando la anotación @Converter y en otra alternativa de persistencia para Java como jOOQ especificando en el generador el tipo que se quiere usar para una columna. En ambos casos hay que proporcionar una implementación que convierta del tipo de la base de datos al del identificador en el dominio y viceversa. Son muy simples.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
packageio.github.picodotdev.infrastructure.datasource.hibernate.converter;importjavax.persistence.AttributeConverter;importjavax.persistence.Converter;importio.github.picodotdev.domain.event.EventId;@ConverterpublicclassEventIdConverterimplementsAttributeConverter<EventId,Long>{@OverridepublicLongconvertToDatabaseColumn(EventIdid){returnid.getValue();}@OverridepublicEventIdconvertToEntityAttribute(Longvalue){returnnewEventId(value);}}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
packageio.github.picodotdev.infrastructure.datasource.jooq.converter;importio.github.picodotdev.domain.event.EventId;publicclassEventIdConverterimplementsConverter<Long,EventId>{@OverridepublicClass<Long>fromType(){returnLong.class;}@OverridepublicEventIdfrom(Longvalue){returnnewEventId(value);}@OverridepublicLongto(EventIdid){returnid.getValue());}@OverridepublicClass<EventId>toType(){returnEventId.class;}}

En una entidad de Hibernate los identificadores se definen de la siguiente forma.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
packageio.github.picodotdev.domain.event;...@EntitypublicclassEvent{@Id@GeneratedValue@Convert(converter=EventIdConverter.class)privateEventIdid;...}

En jOOQ en la configuración del generador hay que especificar que para un campo se use un converter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
plugins{id'java'...id'nu.studer.jooq'version'3.0.3'}...jooq{version=versions.jooqedition='OSS'mysql(sourceSets.main){jdbc{driver='com.mysql.cj.jdbc.Driver'url="jdbc:mysql://localhost:3306/${mysqlDdlJooqSchema}"user='root'password=''}generator{name='org.jooq.codegen.DefaultGenerator'database{name='org.jooq.meta.mysql.MySQLDatabase'inputSchema=mysqlDdlJooqSchemaoutputSchema='application'includes=""" event
"""excludes=''...forcedTypes{...// Ids
forcedType{types='BIGINT'userType='io.github.picodotdev.domain.event.EventId'converter='io.github.picodotdev.infrastructure.datasource.jooq.converter.EventIdConverter'expression='.*\\.event\\.id'}}}generate{javaTimeTypes=trueinterfaces=falsepojos=truerecords=truerelations=true}target{packageName='io.github.picodotdev.infrastructure.datasource.jooq.entities'directory='src/main/java-generated'}}}}...

Con un tipo de datos propio para los identificadores es muy importante implementar correctamente los métodos equals y hashCode tanto en clases de identificadores como en las entidades de dominio ya que las colecciones de Java se basan en estos métodos para determinar si una colección contiene un elemento.


Viewing all articles
Browse latest Browse all 2732

Trending Articles


Vimeo 10.7.1 by Vimeo.com, Inc.


UPDATE SC IDOL: TWO BECOME ONE


KASAMBAHAY BILL IN THE HOUSE


Girasoles para colorear


Presence Quotes – Positive Quotes


EASY COME, EASY GO


Love with Heart Breaking Quotes


Re:Mutton Pies (lleechef)


Ka longiing longsem kaba skhem bad kaba khlain ka pynlong kein ia ka...


Vimeo 10.7.0 by Vimeo.com, Inc.


FORECLOSURE OF REAL ESTATE MORTGAGE


FORTUITOUS EVENT


Pokemon para colorear


Sapos para colorear


Smile Quotes


Letting Go Quotes


Love Song lyrics that marks your Heart


RE: Mutton Pies (frankie241)


Hato lada ym dei namar ka jingpyrshah jong U JJM Nichols Roy (Bah Joy) ngin...


Long Distance Relationship Tagalog Love Quotes