Spring Data JPA JDBC 语句 MADNESS [重复]

Posted

技术标签:

【中文标题】Spring Data JPA JDBC 语句 MADNESS [重复]【英文标题】:Spring Data JPA JDBC statements MADNESS [duplicate] 【发布时间】:2018-08-27 08:26:39 【问题描述】:

我有一个简单的实体:

@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 条语句发送到 DB:

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 中的所有数据(ok mb 2-3 statements)?

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

渴望没有帮助

我知道,我可以从 DishType 中删除 dishTypeLocales,然后在 2 个单独的方法中获取所有 dishTypes,然后获取所有 dishTypeLocales,然后在代码中映射它们,但是还有更好的方法吗?

我正在使用:

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

数据库:Postgresql 9.6

【问题讨论】:

这是最小的工作示例吗? 【参考方案1】:

您遇到了关系的延迟加载,这是OneToMany 关系的默认行为。

这里有 4 个选项:

    为关系设置 EAGER 加载(我知道您写道,您已经尝试过但没有成功,但相信我,它有效。您可能只是遇到了不同的问题) 使用FETCH JOIN 加载实体和关系。为此,您必须使用以下查询(草稿)在存储库中编写自定义方法:SELECT dt FROM DishType dt JOIN FETCH dt.dishTypeLocales 使用 Spring Data JPA 的功能,Fetch/LoadGraph 使用projections,因为这是一个只读操作。最好在读取数据时避免使用实体,仅在修改数据时使用实体。

【讨论】:

以上是关于Spring Data JPA JDBC 语句 MADNESS [重复]的主要内容,如果未能解决你的问题,请参考以下文章

markdown jdbc,jpa,spring data jpa,hibernate,mybatis区别

Spring Data JDBC / Spring Data JPA 与 Hibernate

Spring Data JPA 中的 JDBC CommunicationsException

springjdbc执行自定义sql

Spring Data JDBC 详解

Spring Data JDBC 详解