Таким образом, у меня есть 3 сущности, Employee
, Shop
и EmployeeShop
, которые являются ссылочной сущностью для Employee
и Shop
.
@Entity
@Table(name = "employee_shops")
class EmployeeShop(
@Id
@ManyToOne
var employee: Employee? = null,
@Id
@ManyToOne
var shop: Shop? = null
) : Serializable {
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other == null || javaClass != other.javaClass) {
return false
}
other as EmployeeShop
return Objects.equals(employee, other.employee) &&
Objects.equals(shop, other.shop)
}
override fun hashCode(): Int {
return Objects.hash(employee, shop)
}
}
Сотрудник
@Entity
@Table(name = "employees")
class Employee(
@Id
var id: Int? = null,
var userName: String? = null,
var email: String? = null
@OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL], orphanRemoval = true)
var shops: MutableList<EmployeeShop> = mutableListOf()
) {
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other == null || javaClass != other.javaClass) {
return false
}
other as Employee
return Objects.equals(userName, other.userName) &&
Objects.equals(email, other.email)
}
override fun hashCode(): Int {
return Objects.hash(userName, email)
}
}
И Магазин
@Entity
@Table(name = "shops")
class Shop(
@Id
var id: Int? = null,
@OneToMany(mappedBy = "shop", cascade = [CascadeType.ALL], orphanRemoval = true)
var users: MutableList<EmployeeShop> = mutableListOf(),
) {
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
if (other == null || javaClass != other.javaClass) {
return false
}
other as Shop
return Objects.equals(id, other.id)
}
override fun hashCode(): Int {
return Objects.hash(id)
}
}
EmployeeRepository
выглядит примерно так
interface EmployeeRepository: CrudRepository<Employee, String> {
@Query(value = "SELECT e FROM Employee e LEFT JOIN FETCH e.shops WHERE e.id = :id")
override fun findById(id: String): Optional<Employee>
}
Причина, по которой я переопределяю это, заключается в добавлении LEFT JOIN FETCH
, чтобы избежать LazyInitializationException
Чтобы вернуться из API, я преобразую Employee
в EmployeeDto
fun getDto(entity: Employee): EmployeeDto {
return EmployeeDto(
userName = entity.userName,
email = entity.email
shops = entity.shops.map { IdAndNameDto(it.shop?.id?.toString().orEmpty(), it.shop?.name.orEmpty()) }
)
}
class IdAndNameDto(val id: String = "", val name: String = "")
class EmployeeDto(
val userName: String,
val email: String,
val shops: List<IdAndNameDto>?
)
Когда я использую репозиторий в , обновление * Employee
employeeRepo.save(employee)
save
от CrudRepository
( do c). Здесь save
должен возвращать экземпляр Employee
.
Я получаю следующую трассировку стека
java.lang.StackOverflowError: null
at ch.qos.logback.classic.spi.TurboFilterList.getTurboFilterChainDecision(TurboFilterList.java:49) ~[logback-classic-1.2.3.jar:na]
at ch.qos.logback.classic.LoggerContext.getTurboFilterChainDecision_0_3OrMore(LoggerContext.java:269) ~[logback-classic-1.2.3.jar:na]
at ch.qos.logback.classic.Logger.callTurboFilters(Logger.java:751) ~[logback-classic-1.2.3.jar:na]
at ch.qos.logback.classic.Logger.isTraceEnabled(Logger.java:623) ~[logback-classic-1.2.3.jar:na]
at org.apache.logging.slf4j.SLF4JLogger.isEnabledFor(SLF4JLogger.java:213) ~[log4j-to-slf4j-2.12.1.jar:2.12.1]
at org.apache.logging.slf4j.SLF4JLogger.isEnabled(SLF4JLogger.java:121) ~[log4j-to-slf4j-2.12.1.jar:2.12.1]
at org.apache.logging.log4j.spi.AbstractLogger.isEnabled(AbstractLogger.java:1505) ~[log4j-api-2.12.1.jar:2.12.1]
at org.jboss.logging.Log4j2Logger.isEnabled(Log4j2Logger.java:46) ~[jboss-logging-3.4.1.Final.jar:3.4.1.Final]
at org.jboss.logging.Logger.isTraceEnabled(Logger.java:98) ~[jboss-logging-3.4.1.Final.jar:3.4.1.Final]
at org.jboss.logging.DelegatingBasicLogger.isTraceEnabled(DelegatingBasicLogger.java:54) ~[jboss-logging-3.4.1.Final.jar:3.4.1.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:502) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1176) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1041) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:464) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:457) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ComponentType.resolve(ComponentType.java:695) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:878) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:732) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.processResultSet(Loader.java:1008) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:964) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2410) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:63) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4396) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4386) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:569) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:537) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1176) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1041) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:464) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:457) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ComponentType.resolve(ComponentType.java:695) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:878) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:732) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.processResultSet(Loader.java:1008) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:964) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2410) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:63) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4396) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4386) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
...
Остальная часть трассировки стека просто повторяет эти несколько строк, которые вы также можно увидеть из приведенного выше стека трассировки
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:502) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1176) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1041) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:464) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:457) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.type.ComponentType.resolve(ComponentType.java:695) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:878) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:732) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.processResultSet(Loader.java:1008) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:964) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2410) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:74) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:63) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4396) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4386) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
Но у меня нет ошибок при попытке создать Сотрудника с тем же методом save
.
Кроме того, это происходит только в том случае, если сущность сотрудника содержит непустой объект shops
. Если shop
пусто, что означает, что Employee
, который я получил с помощью findById
, не содержит записей в таблице ссылок EmployeeShop
, тогда обновление также не выдает ошибку.
Я все еще новичок в JPA, поэтому я подозреваю, что способ, которым я объявил эти сущности, например, как я использую аннотации, не верен. Но я не уверен, в чем проблема.
Кто-нибудь знает, почему я получил ошибку StackOverflow?