Skip to content

Commit

Permalink
Fix regression with Enums not being persisted using toString (#1531)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstepanov authored May 17, 2022
1 parent 56b4ac3 commit a7c9e04
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.micronaut.data.jdbc.h2

import io.micronaut.context.ApplicationContext
import io.micronaut.core.annotation.Introspected
import io.micronaut.data.annotation.GeneratedValue
import io.micronaut.data.annotation.Id
import io.micronaut.data.annotation.MappedEntity
Expand All @@ -14,12 +15,11 @@ import io.micronaut.data.model.query.builder.sql.Dialect
import io.micronaut.data.model.query.builder.sql.SqlQueryBuilder
import io.micronaut.data.repository.CrudRepository
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.AutoCleanup
import spock.lang.PendingFeature
import spock.lang.Shared
import spock.lang.Specification

import jakarta.inject.Inject
import javax.persistence.Entity
import javax.persistence.EnumType
import javax.persistence.Enumerated
Expand All @@ -46,7 +46,7 @@ class H2EnumsMappingSpec extends Specification implements H2TestPropertyProvider

void 'test read lower case enum'() {
when:
enumEntityRepository.insertValueExplicit("b", "B")
enumEntityRepository.insertValueExplicit("B", "b")
def result = enumEntityRepository.findByAsString(MyEnum.B)

then:
Expand All @@ -68,6 +68,12 @@ class H2EnumsMappingSpec extends Specification implements H2TestPropertyProvider
entity.asDefault == MyEnum.A
entity.asString == MyEnum.B
entity.asInt == MyEnum.C
when:
def dto = enumEntityRepository.queryById(entity.id)
then:
dto.asDefault == "a"
dto.asString == "b"
dto.asInt == 2
when:
int updated = enumEntityRepository.update(entity.id, MyEnum.D, MyEnum.E, MyEnum.F)
entity = enumEntityRepository.findById(entity.id).get()
Expand Down Expand Up @@ -159,6 +165,8 @@ abstract class EnumEntityRepository implements CrudRepository<EnumEntity, Long>

abstract Optional<EnumEntity> find(MyEnum asDefault, MyEnum asString, MyEnum asInt)

abstract EnumEntityDto queryById(Long id)

}

@JdbcRepository(dialect = Dialect.H2)
Expand All @@ -183,6 +191,14 @@ class EnumEntity {
MyEnum asInt
}

@Introspected
class EnumEntityDto {

String asDefault
String asString
Object asInt
}

@Entity
class JpaEnumEntity {
@javax.persistence.Id
Expand All @@ -197,4 +213,9 @@ class JpaEnumEntity {

enum MyEnum {
A, B, C, D, E, F

@Override
String toString() {
return name().toLowerCase();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,14 @@ private boolean isDtoType(ClassElement classElement) {
private List<SourcePersistentProperty> getDtoProjectionProperties(SourcePersistentEntity entity,
ClassElement returnType) {
return returnType.getBeanProperties().stream()
.filter(beanProperty -> {
String propertyName = beanProperty.getName();
.filter(dtoProperty -> {
String propertyName = dtoProperty.getName();
// ignore Groovy meta class
return !"metaClass".equals(propertyName) || !beanProperty.getType().isAssignable("groovy.lang.MetaClass");
return !"metaClass".equals(propertyName) || !dtoProperty.getType().isAssignable("groovy.lang.MetaClass");
})
.map(beanProperty -> {
String propertyName = beanProperty.getName();
if ("metaClass".equals(propertyName) && beanProperty.getType().isAssignable("groovy.lang.MetaClass")) {
.map(dtoProperty -> {
String propertyName = dtoProperty.getName();
if ("metaClass".equals(propertyName) && dtoProperty.getType().isAssignable("groovy.lang.MetaClass")) {
// ignore Groovy meta class
return null;
}
Expand All @@ -292,8 +292,13 @@ private List<SourcePersistentProperty> getDtoProjectionProperties(SourcePersiste
throw new MatchFailedException("Property " + propertyName + " is not present in entity: " + entity.getName());
}

if (!TypeUtils.areTypesCompatible(beanProperty.getType(), pp.getType())) {
throw new MatchFailedException("Property [" + propertyName + "] of type [" + beanProperty.getType().getName() + "] is not compatible with equivalent property declared in entity: " + entity.getName());
ClassElement dtoPropertyType = dtoProperty.getType();
if (dtoPropertyType.getName().equals("java.lang.Object") || dtoPropertyType.getName().equals("java.lang.String")) {
// Convert anything to a string or an object
return pp;
}
if (!TypeUtils.areTypesCompatible(dtoPropertyType, pp.getType())) {
throw new MatchFailedException("Property [" + propertyName + "] of type [" + dtoPropertyType.getName() + "] is not compatible with equivalent property of type [" + pp.getType().getName() + "] declared in entity: " + entity.getName());
}
return pp;
}).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class PersonDto {
""")
then:
def e = thrown(RuntimeException)
e.message.contains('Property [name] of type [int] is not compatible with equivalent property declared in entity: io.micronaut.data.model.entities.Person')
e.message.contains('Property [name] of type [int] is not compatible with equivalent property of type [java.lang.String] declared in entity: io.micronaut.data.model.entities.Person')
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ default QueryStatement<PS, IDX> setDynamic(
if (value instanceof CharSequence) {
str = value.toString();
} else if (value instanceof Enum) {
str = ((Enum<?>) value).name();
str = value.toString();
} else {
str = convertRequired(value, String.class);
}
Expand Down

0 comments on commit a7c9e04

Please sign in to comment.