Created
September 8, 2020 07:08
-
-
Save azami/68d72ff985883510d603dd10c7156890 to your computer and use it in GitHub Desktop.
PostgreSQL + JPA + Hibernate Set<Enum> (Collection) Descriptor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.vladmihalcea.hibernate.type.array.internal.AbstractArrayTypeDescriptor | |
import com.vladmihalcea.hibernate.type.array.internal.ArrayUtil | |
import org.hibernate.type.descriptor.WrapperOptions | |
import org.hibernate.type.descriptor.java.MutableMutabilityPlan | |
class CollectionMutableMutabilityPlan<T> : MutableMutabilityPlan<Collection<T>?>() { | |
override fun deepCopyNotNull(value: Collection<T>?): Collection<T>? { | |
return value?.map { it } | |
} | |
} | |
@Suppress("UNCHECKED_CAST") | |
abstract class CollectionTypeDescriptor<T>(private val collection: Collection<*>) : | |
AbstractArrayTypeDescriptor<Collection<T>>( | |
emptyList<T>()::class.java as Class<Collection<T>>, | |
CollectionMutableMutabilityPlan<T>() | |
) { | |
abstract fun toSQLValue(value: T): String | |
abstract fun toValue(value: String): T | |
override fun <X : Any?> unwrap(value: Collection<T>?, type: Class<X>?, options: WrapperOptions?): X? { | |
if (value == null) return null | |
return value.map { toSQLValue(it) }.toTypedArray() as X | |
} | |
private fun <T> format(values: List<T>): Collection<T> { | |
return when (collection) { | |
is Set<*> -> values.toSet() | |
is List<*> -> values | |
else -> | |
throw UnsupportedOperationException("The $collection is not supported yet!") | |
} | |
} | |
override fun <X : Any?> wrap(value: X, options: WrapperOptions?): Collection<T>? { | |
if (value == null) return null | |
return when (value) { | |
is org.postgresql.jdbc.PgArray -> { | |
val values = (value.array as Array<String>).map { toValue(it) } | |
format(values) | |
} | |
else -> value.run { | |
throw UnsupportedOperationException("The ${this::class.java} is not supported yet!") | |
} | |
} | |
} | |
override fun areEqual(one: Any?, another: Any?): Boolean { | |
return one == another | |
} | |
override fun fromString(string: String?): Collection<T>? { | |
val converted = ArrayUtil.fromString(string, emptyArray<String>()::class.java) | |
return listOf(*converted).map { toValue(it) } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Entity | |
@Table(name = "foo_table") | |
@TypeDefs( | |
value = [ | |
TypeDef(name = "excamples", typeClass = ExamplesDialect::class), | |
] | |
) | |
data class InsertionOrder( | |
@Id | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | |
val id: Int?, | |
@Column | |
@get:NotNull | |
@get:Size(min = 1, max = 255) | |
var name: String?, | |
@Column | |
@Type(type = "examples") | |
var examples: MutableSet<Example>?, | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExamplesDialect: | |
AbstractHibernateType<Collection<Example>>(ArraySqlTypeDescriptor.INSTANCE, ExamplesDescriptor()), | |
DynamicParameterizedType { | |
override fun registerUnderJavaType(): Boolean { | |
return true | |
} | |
override fun setParameterValues(parameters: Properties) { | |
} | |
companion object { | |
val INSTANCE = ExamplesDialect() | |
} | |
override fun getName(): String { | |
return "examples" | |
} | |
class ExamplesDescriptor : CollectionTypeDescriptor<Example>(emptySet<Example>()) { | |
override fun toSQLValue(value: Example): String { | |
return value.name.toLowerCase() | |
} | |
override fun toValue(value: String): Example { | |
return Example.valueOf(value.toUpperCase()) | |
} | |
override fun getSqlArrayType(): String { | |
return "channel" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment