JPA注释ElementCollection渴望在春季启动时获取

时间:2020-04-08 16:08:10

标签: hibernate spring-boot jpa kotlin

我在弹簧靴中热切地抓取一个小问题。基本上,我有一个实体定义为:

@Entity
class EventEntry(
        @ID
        val uid 

        @ElementCollection(fetch = FetchType.EAGER)
        @CollectionTable(name = "event_to_boxes", joinColumns = arrayOf(JoinColumn(name = "event_uid")))
        @Column(name = "box_uid")
        val boxUids: List<Long>
) : EventEntry(userUid, timestamp)

现在,当我插入数据(来自graphql,但很详细)时,一切正常,并且我可以看到在数据库上,多行正确地保留在event_to_boxes表上。 不幸的是,当我检索所有事件时,突然出现了一些意外情况。

我看到的是查询所有事件的查询,然后对boxUids的每个列表询问一次,几乎就像FetchType.EAGER被完全忽略了。

我的理解是,在填充事件实体时,渴望获取类型的对象应该已经获得了框uid的值。 我有什么想念的吗?还是我的理解是完全错误的?

为了提供更多背景知识,我正在尝试以此方式建立N对N关系,这是N关系的一半,但是我必须在获取事件实体时也要提出框uid(框是关系的另一半),没有任何其他框数据

1 个答案:

答案 0 :(得分:0)

如休眠documentation中所述,from PyQt5 import QtCore, QtGui, QtWidgets #from afterlogin import Ui_afterloginwindow class Ui_afterloginwindow(object): def setupUi(self, afterloginwindow): afterloginwindow.setObjectName("afterloginwindow") afterloginwindow.resize(720, 480) afterloginwindow.setMinimumSize(QtCore.QSize(720, 480)) afterloginwindow.setMaximumSize(QtCore.QSize(720, 480)) afterloginwindow.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0,\ x2:1, y2:1, stop:0 rgba(35, 226, 167, 255), stop:1 rgba(255, 255, 255, 255));") self.centralwidget = QtWidgets.QWidget(afterloginwindow) self.centralwidget.setObjectName("centralwidget") self.newclient = QtWidgets.QPushButton(self.centralwidget) self.newclient.setGeometry(QtCore.QRect(230, 120, 241, 91)) font = QtGui.QFont() font.setFamily("Rockwell Extra Bold") font.setPointSize(16) font.setBold(True) font.setWeight(75) self.newclient.setFont(font) self.newclient.setStyleSheet("background-color: qconicalgradient(cx:1, cy:0.875, angle:0,\ stop:0 rgba(255, 124, 0, 255), stop:1 rgba(255, 255, 255, 255));\n" "background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:1, stop:0.318182 rgba(226,\ 198, 94, 255), stop:1 rgba(207, 207, 207, 255));") self.newclient.setObjectName("newclient") self.renew = QtWidgets.QPushButton(self.centralwidget) self.renew.setGeometry(QtCore.QRect(230, 250, 241, 91)) font = QtGui.QFont() font.setFamily("Rockwell Extra Bold") font.setPointSize(15) font.setBold(True) font.setWeight(75) self.renew.setFont(font) self.renew.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1,\ y2:1, stop:0 rgba(146, 237, 241, 255), stop:1 rgba(255, 255, 255, 255));") self.renew.setObjectName("renew") self.newcard = QtWidgets.QPushButton(self.centralwidget) self.newcard.setGeometry(QtCore.QRect(230, 380, 241, 91)) font = QtGui.QFont() font.setFamily("Rockwell Extra Bold") font.setPointSize(15) font.setBold(True) font.setWeight(75) self.newcard.setFont(font) self.newcard.setStyleSheet("background-color: qconicalgradient(cx:0, cy:0, angle:135, stop:0 \ rgba(255, 255, 0, 69), stop:0.375 rgba(255, 255, 0, 69), stop:0.423533 rgba(251, 255, 0, 145), \ stop:0.45 rgba(247, 255, 0, 208), stop:0.477581 rgba(255, 244, 71, 130), stop:0.518717 rgba(255, \ 218, 71, 130), stop:0.55 rgba(255, 255, 0, 255), stop:0.57754 rgba(255, 203, 0, 130), stop:0.625 \ rgba(255, 255, 0, 69), stop:1 rgba(255, 255, 0, 69));") self.newcard.setObjectName("newcard") self.rechercher = QtWidgets.QPushButton(self.centralwidget) self.rechercher.setGeometry(QtCore.QRect(230, 10, 241, 81)) font = QtGui.QFont() font.setFamily("Rockwell Extra Bold") font.setPointSize(16) font.setBold(True) font.setWeight(75) self.rechercher.setFont(font) self.rechercher.setObjectName("rechercher") afterloginwindow.setCentralWidget(self.centralwidget) self.retranslateUi(afterloginwindow) QtCore.QMetaObject.connectSlotsByName(afterloginwindow) def retranslateUi(self, afterloginwindow): _translate = QtCore.QCoreApplication.translate afterloginwindow.setWindowTitle(_translate("afterloginwindow", "MainWindow")) self.newclient.setText(_translate("afterloginwindow", "Nouveau Client ")) self.renew.setText(_translate("afterloginwindow", "Renouvellement ")) self.newcard.setText(_translate("afterloginwindow", "Nouvelle Carte ")) self.rechercher.setText(_translate("afterloginwindow", "Rechercher")) class Ui_login(object): def setupUi(self, login): login.setObjectName("login") login.resize(720, 480) login.setMinimumSize(QtCore.QSize(720, 480)) login.setMaximumSize(QtCore.QSize(720, 480)) login.setStyleSheet("background-color: rgb(255, 255, 255);\n" "background-color: rgb(255, 85, 0);") self.centralwidget = QtWidgets.QWidget(login) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(290, 390, 171, 71)) self.pushButton.setStyleSheet("background-color: rgb(255, 255, 255);") self.pushButton.setObjectName("pushButton") self.pushButton.clicked.connect(self.login) self.username = QtWidgets.QLabel(self.centralwidget) self.username.setGeometry(QtCore.QRect(170, 165, 161, 31)) self.username.setStyleSheet("background-color: rgb(255, 255, 255);") self.username.setObjectName("username") self.password = QtWidgets.QLabel(self.centralwidget) self.password.setGeometry(QtCore.QRect(170, 225, 171, 41)) self.password.setStyleSheet("background-color: rgb(255, 255, 255);") self.password.setObjectName("password") self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(400, 170, 113, 20)) self.lineEdit.setStyleSheet("background-color: rgb(255, 255, 255);") self.lineEdit.setObjectName("lineEdit") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(400, 240, 113, 20)) self.lineEdit_2.setStyleSheet("background-color: rgb(255, 255, 255);") self.lineEdit_2.setObjectName("lineEdit_2") login.setCentralWidget(self.centralwidget) self.retranslateUi(login) QtCore.QMetaObject.connectSlotsByName(login) def retranslateUi(self, login): _translate = QtCore.QCoreApplication.translate login.setWindowTitle(_translate("login", "MainWindow")) self.pushButton.setText(_translate("login", "login ")) self.username.setText(_translate("login", "username")) self.password.setText(_translate("login", "password ")) class AfterLoginWindow(QtWidgets.QMainWindow, Ui_afterloginwindow): def __init__(self): super().__init__() self.setupUi(self) class MyWin(QtWidgets.QMainWindow, Ui_login): def __init__(self): super().__init__() self.setupUi(self) def login(self): username = self.lineEdit.text() password = self.lineEdit_2.text() if username == "admin" and password == "admin": self.window = AfterLoginWindow() self.window.show() self.hide() else: msg = QtWidgets.QMessageBox.information(None, 'Error', 'Something went wrong, try again.') if __name__=="__main__": import sys app = QtWidgets.QApplication(sys.argv) myapp = MyWin() myapp.show() sys.exit(app.exec_()) 仅适用于直接实体获取:

FetchType.EAGER

EventEntry eventEntry = entityManager.find(EventEntry.class, 1L); 子句已添加到生成的SQL查询中,因为需要热切地获取此关联。

另一方面,如果您使用的实体查询不包含LEFT JOIN指令...

Hibernate改为使用辅助选择。这是因为实体查询的提取策略无法被覆盖,因此Hibernate需要进行二次选择,以确保在将结果返回给用户之前,已提取JOIN FETCH关联。

如果您忘记了EAGER的所有JOIN FETCH关联,则Hibernate将为每个关联发出第二选择,从而导致N + 1查询问题。 / p>

因此,您应该首选LAZY关联。