如何使用Spring Data JPA选择@ElementCollection属性?

时间:2018-08-24 16:55:59

标签: java spring-boot kotlin spring-data-jpa

我有以下实体:

@Entity
data class PieEntity(
        @get:Column
        var name: String = "name",

        @get:Enumerated(EnumType.STRING)
        @get:ElementCollection
        var ingredients: MutableSet<PieIngredient> = mutableSetOf(PieIngredient.A, PieIngredient.B),

        // lots of other properties...

        @get:Id
        @get:GeneratedValue
        var id: Long? = null)

enum class PieIngredient { A, B, C }

现在,我只想选择其属性的子集,在本例中为nameingredients属性。

目前,我发现了4种可能的解决方案,但是它们都有缺陷:

解决方案1 ​​

使用基于类的投影:

data class PiePreviewDto(
    val name: String,
    val ingredients: PieIngredient)

@Repository
interface PieRepository : JpaRepository<PieEntity, Long> {
    fun findTop3ByOrderByNameDesc(): List<PiePreviewDto>
}

这将创建一个select语句,该语句仅选择所需的属性。

这里的问题是每种配料的每个派都得到一个结果。例如,如果我有2个饼,每种饼含2种成分,我将得到4个结果,这意味着我必须手动合并这些结果,这似乎是不可取的。

解决方案2

使用投影:

interface PiePreview {
    val name: String
    val ingredients: MutableSet<PieIngredient>
}

@Repository
interface PieRepository : JpaRepository<PieEntity, Long> {
    fun findTop3ByOrderByNameDesc(): List<PiePreview>
}

在这里,我每个饼得到一个结果(很好)。

问题在于它实际上选择了所有属性,并且我有一些我不想选择的“凸角”(因此正是这个问题)。

解决方案3

使用字节码编织,这样我就可以懒惰地获取所有内容(甚至是@Basic属性)。

我没有尝试此操作,因为它似乎是特定于供应商的。但是,如果这是最理智的解决方案,我愿意尝试一下。

解决方案4

具有转换器和基于类的投影的重复属性:

@Entity
data class PieEntity(
        @get:Column
        var name: String = "name",

        @get:Convert(converter = PieIngredientSetConverter::class)
        var ingredients: MutableSet<PieIngredient> = mutableSetOf(A, B),

        @get:Enumerated(EnumType.STRING)
        @get:ElementCollection
        var ingredientSet: MutableSet<PieIngredient> = mutableSetOf(A, B),

        // lots of other properties...

        @get:Id
        @get:GeneratedValue
        var id: Long? = null)

class PieIngredientSetConverter : AttributeConverter<MutableSet<PieIngredient>, String> {
    override fun convertToDatabaseColumn(attribute: MutableSet<PieIngredient>) =
            attribute.joinToString(",") { it.name }

    override fun convertToEntityAttribute(dbData: String) =
            dbData.split(PATTERN).map { PieIngredient.valueOf(it) }.toMutableSet()
}

data class PiePreviewDto(
    val name: String,
    val ingredients: MutableSet<PieIngredient>)

@Repository
interface PieRepository : JpaRepository<PieEntity, Long> {
    fun findTop3ByOrderByNameDesc(): List<PiePreviewDto>
}

这只会选择我想要的属性。

问题在于我必须手动同步重复的属性,它使用更多的磁盘空间(对我而言并不是真正的问题),并且需要对其进行转换。

由于我执行ingredientSet查询(搜索成分),因此我需要IN属性。


是否有更好/改进的解决方案?

0 个答案:

没有答案