Операторы Spring Data JPA JDBC БЕЗУМИЕ

У меня простая сущность:

@Entity
@Table(name = "dish_type")
class DishType : Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long = -1
    var name: String? = null
    var description: String? = null
    @OneToMany(mappedBy = "dishType")
    var dishTypeLocales: List<DishTypeLocale>? = null
}

@Entity
@Table(name = "dish_type_locale")
class DishTypeLocale : Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long = -1

    @Enumerated(EnumType.STRING)
    var locale: LocaleString? = null
    var value: String? = null

    @ManyToOne
    @JoinColumn(name = "dish_type_id")
    var dishType: DishType? = null
}

ДАО:

interface DishTypeService {
    fun findAll(withLocale: Boolean): List<DishTypeDto>
}

@Service
@Transactional
open class DishTypeServiceImpl(private val dishTypeRepository: DishTypeRepository) : DishTypeService {

    override fun findAll(withLocale: Boolean): List<DishTypeDto> {
        return this.dishTypeRepository.findAll().map { DishTypeDto(it, withLocale) }
    }

}

@Repository
interface DishTypeRepository : JpaRepository<DishType, Long>

DTO:

class DishTypeDto {
    var id: Long = -1
    var description: String? = null
    var locale: List<DefaultLocalizationDto>? = null

    constructor()

    constructor(dishType: DishType, withLocale: Boolean) {
        this.id = dishType.id
        this.description = dishType.description
        if (withLocale) {
            this.locale = dishType.dishTypeLocales?.map { DefaultLocalizationDto(it) }
        }
    }

    override fun toString(): String {
        return "DishTypeDto{" +
                "id = " + id +
                ", description='" + description + '\'' +
                '}'
    }
}


class DefaultLocalizationDto {
    var locale: Int? = null
    var name: String? = null
    var description: String? = null

    constructor()

    constructor(locale: DishTypeLocale) {
        this.locale = locale.locale?.code
        this.name = locale.value
    }

    override fun toString(): String = "DefaultLocalizationDto(locale=$locale, name=$name, description=$description)"
}

В случае DishTypeService.findAll(false) у нас есть 1 инструкция к БД:

Session Metrics {
    6789040 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    146499 nanoseconds spent preparing 1 JDBC statements;
    3929488 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    43774 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

В случае операторов DishTypeService.findAll(true) == table.size (в моем случае 282):

Session Metrics {
    11570010 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    4531164 nanoseconds spent preparing 282 JDBC statements;
    60280410 nanoseconds spent executing 282 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    60464 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

Как сообщить Spring, чтобы получить все данные в 1 (хорошо, mb 2-3 утверждения)?

@OneToMany(mappedBy = "dishType", fetch = FetchType.EAGER)
var dishTypeLocales: List<DishTypeLocale>? = null

EAGER не помог

Я знаю, я могу удалить dishTypeLocales из DishType и двумя отдельными методами получить все dishTypes, затем все dishTypeLocales, а затем их кодовую карту, но мб, есть какой-то лучший способ?

Я использую:

    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>

БД: Postgresql 9.6

Это минимальный рабочий пример?

Michael Piefel 18.03.2018 20:34
0
1
448
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы испытываете отложенную загрузку отношений, которая является поведением по умолчанию для отношений OneToMany.

Здесь у вас есть 4 варианта:

  1. Установите загрузку EAGER для отношений (я знаю, что вы написали, что уже пробовали это, и это не сработало, но поверьте мне, это работает. Просто у вас, вероятно, возникла другая проблема)
  2. Используйте FETCH JOIN для загрузки объекта вместе с отношением. Для этого вам нужно написать собственный метод в вашем репозитории со следующим запросом (черновиком): SELECT dt FROM DishType dt JOIN FETCH dt.dishTypeLocales
  3. Используйте функцию Spring Data JPA, Получить / LoadGraph
  4. Используйте прогнозы, так как это операция только для чтения. Лучше избегать использования сущностей при чтении данных и придерживаться их только при изменении данных.

Другие вопросы по теме