Проблема загрузки OneToOne при весенней загрузке - PullRequest
1 голос
/ 31 мая 2019

Мне нужно получить данные из базы данных без каких-либо полей, но я получаю или ВСЕ данные (с отношением) или ошибка.

import org.springframework.data.domain.Persistable
import org.springframework.data.util.ProxyUtils
import java.io.Serializable
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.MappedSuperclass
import javax.persistence.Transient

@MappedSuperclass
abstract class AbstractEntity<T : Serializable>() : Persistable<T> {

    companion object {
        private val serialVersionUID = -5554308939380869754L
    }

    @Id
    @GeneratedValue
    private var id: T? = null

    override fun getId(): T? {
        return id
    }

    fun setId(id:T){
        this.id = id
    }

    /**
     * Must be [Transient] in order to ensure that no JPA provider complains because of a missing setter.
     *
     * @see org.springframework.data.domain.Persistable.isNew
     */
    @Transient
    override fun isNew() = null == getId()

    override fun toString() = "Entity of type ${this.javaClass.name} with id: $id"

    override fun equals(other: Any?): Boolean {
        other ?: return false

        if (this === other) return true

        if (javaClass != ProxyUtils.getUserClass(other)) return false

        other as AbstractEntity<*>

        return if (null == this.getId()) false else this.getId() == other.getId()
    }

    override fun hashCode(): Int {
        return 31
    }
}

ProductEntity:

@Entity
@Table(name = "product")
class ProductEntity : AbstractEntity<Long> {
    @Column(name = "product_name")
    var productName: String = ""
    @Column(name = "description", length = 65535, columnDefinition = "text")
    var description: String = ""
    @Column(name = "product_model")
    var productModel: String = ""
    @Column(name = "product_articul")
    var productArticul: String = ""
    @Column(name = "product_count")
    var productCount: Int = 0
    @Column(name = "is_available")
    var isAvailable: Boolean = false
    @Column(name = "product_price")
    var productPrice: Float = 0f
    @Column(name = "product_extra")
    var productExtra: Float = 0f
    @Column(name = "product_total_price")
    var productTotalPrice: Float = 0f
    @OneToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE], orphanRemoval = false, fetch = FetchType.LAZY)
    var productCategoryProperty: ProductCategoryPropertyEntity = ProductCategoryPropertyEntity()
    @OneToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE], fetch = FetchType.LAZY)
    var category: CategoryEntity = CategoryEntity()
    @Column(name = "images")
    var images: Array<String?> = arrayOf()
    @Column(name = "keywords", length = 65535, columnDefinition = "text")
    var keywords: String? = ""

    constructor() : super() {
    }

    fun convertToDto(): ProductDto {
        return ProductDto(id, productName, description, productModel, productArticul,
                productCount, productPrice, productExtra, productTotalPrice, isAvailable,
                productCategoryProperty?.convertToDto(), category?.convertToDto(), images, keywords)
    }
}

ProductCategoryPropertyEntity:

import ua.jdroidcoder.jdcshop.dto.ProductCategoryPropertyDto
import javax.persistence.*

@Entity
@Table(name = "product_category_property")
class ProductCategoryPropertyEntity : AbstractEntity<Long> {

    @OneToMany(cascade = [CascadeType.PERSIST, CascadeType.MERGE], orphanRemoval = false)
    var simpleProperties: MutableList<ProductPropertySimpleEntity> = ArrayList()

    @OneToMany(cascade = [CascadeType.PERSIST, CascadeType.MERGE], orphanRemoval = false)
    var advancedProperties: MutableList<ProductPropertySimpleEntity> = ArrayList()

    constructor() : super() {
    }

    fun convertToDto(): ProductCategoryPropertyDto {
        val simple = ProductCategoryPropertyDto()
        simple.id = id
        simpleProperties?.forEach {
            simple.simpleProperties.add(it.convertToDto())
        }
        advancedProperties?.forEach {
            simple.advancedProperties.add(it.convertToDto())
        }
        return simple
    }
}

ProductPropertySimpleEntity:

import ua.jdroidcoder.jdcshop.dto.PropertySimpleDto
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Table

@Entity
@Table(name = "product_property_simple")
class ProductPropertySimpleEntity : AbstractEntity<Long> {
    @Column(name = "property_name")
    var propertyName: String = ""

    @Column(name = "property_value")
    var propertyValue: String = ""

    @Column(name = "parent_id")
    var parentId: Long? = null

    @Column(name = "parent_id_in_category")
    var parentIdInCategory: Long? = null

    @Column(name = "id_in_category")
    var idInCategory: Long? = null

    constructor() : super() {
    }

    fun convertToDto(): PropertySimpleDto {
       return PropertySimpleDto(id!!,propertyName,parentId,propertyValue)
    }
}

Когда я пытаюсь сделать выбор, я вижу:

Hibernate: select productent0_.id as id1_3_, productent0_.category_id as categor13_3_, productent0_.description as descript2_3_, productent0_.images as images3_3_, productent0_.is_available as is_avail4_3_, productent0_.keywords as keywords5_3_, productent0_.product_articul as product_6_3_, productent0_.product_category_property_id as product14_3_, productent0_.product_count as product_7_3_, productent0_.product_extra as product_8_3_, productent0_.product_model as product_9_3_, productent0_.product_name as product10_3_, productent0_.product_price as product11_3_, productent0_.product_total_price as product12_3_ from product productent0_
Hibernate: select categoryen0_.id as id1_0_0_, categoryen0_.category_name as category2_0_0_, categoryen0_.prom_category_id as prom_cat3_0_0_ from category categoryen0_ where categoryen0_.id=?
Hibernate: select productcat0_.id as id1_4_0_ from product_category_property productcat0_ where productcat0_.id=?
Hibernate: select simpleprop0_.product_category_property_entity_id as product_1_6_0_, simpleprop0_.simple_properties_id as simple_p2_6_0_, productpro1_.id as id1_7_1_, productpro1_.id_in_category as id_in_ca2_7_1_, productpro1_.parent_id as parent_i3_7_1_, productpro1_.parent_id_in_category as parent_i4_7_1_, productpro1_.property_name as property5_7_1_, productpro1_.property_value as property6_7_1_ from product_category_property_simple_properties simpleprop0_ inner join product_property_simple productpro1_ on simpleprop0_.simple_properties_id=productpro1_.id where simpleprop0_.product_category_property_entity_id=?
Hibernate: select advancedpr0_.product_category_property_entity_id as product_1_5_0_, advancedpr0_.advanced_properties_id as advanced2_5_0_, productpro1_.id as id1_7_1_, productpro1_.id_in_category as id_in_ca2_7_1_, productpro1_.parent_id as parent_i3_7_1_, productpro1_.parent_id_in_category as parent_i4_7_1_, productpro1_.property_name as property5_7_1_, productpro1_.property_value as property6_7_1_ from product_category_property_advanced_properties advancedpr0_ inner join product_property_simple productpro1_ on advancedpr0_.advanced_properties_id=productpro1_.id where advancedpr0_.product_category_property_entity_id=?

Я знаю, что это происходит через @OneToOne, но я не могу найти решение; (

Мне нужно получить только некоторые поля, такие как: productName, описание, productModel, productArticul, productCount ...

Спасибо за помощь, ребята!

1 Ответ

1 голос
/ 01 июня 2019

@OneToOne сложно, если вы допустите значение null.

JPA необходимо попытаться получить доступ к записи из другой таблицы, даже если свойство подписано lazy-initialization , поскольку оно должно решить, следует ли установить для свойства значение null или прокси-объект.

Он не может установить null автоматически, потому что может быть связанным объектом. Он также не может автоматически создать прокси-объект, поскольку в таблице нет назначенного столбца для идентификатора этого свойства (поскольку отношение «один к одному» по умолчанию отображается совместно используемым PK).

Таким образом, единственный способ решить, существует ли связанная сущность, - это попытаться загрузить ее id из ее собственной таблицы. Если этот запрос возвращает null, то нет связанной сущности, в противном случае JPA может создать прокси-объект с этим идентификатором.

Если вам действительно нужно избежать этого дополнительного запроса, добавьте внешний ключ в таблицу product_category_property в таблицу product.

@OneToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE], orphanRemoval = false, fetch = FetchType.LAZY)
@JoinColumn(name='product_category_property')
var productCategoryProperty: ProductCategoryPropertyEntity = ProductCategoryPropertyEntity()

Вы можете найти дальнейшие объяснения в этой теме .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...