![](/img/trans.png)
[英]Hibernate Lazy loading not working with Spring Boot => failed to lazily initialize a collection of role could not initialize proxy - no Session
[英]Spring Boot, Failed to lazily initialize a collection of role, could not initialize proxy - no Session
我正在制作一個網站,我試圖在其中訂購配料。 我選擇配料並輸入其數量,然后單擊添加。 我重復幾次。 然后我轉到下一頁,我在其中選擇了供應商。 然后我按“訂單”。
預計將 Nabavka 插入數據庫並打開一個頁面說訂單成功,但我得到一個異常,告訴我我不能懶惰地初始化它。
從 NabavkaController.java:
@Autowired
NamirnicaRepository namr;
@Autowired
NabavkaRepository nabr;
@Autowired
DobavljacRepository dr;
@Autowired
NabavkaKorpaRepository nkr;...
@SuppressWarnings("unchecked")
@PostMapping(value = "sacuvajNabavku")
public String sacuvajNabavku(Dobavljac dobavljac, HttpServletRequest request) {
List<Namirnica> izabrane = (ArrayList<Namirnica>) request.getSession()
.getAttribute("izabrane");
List<Integer> brojevi = (ArrayList<Integer>) request.getSession()
.getAttribute("brojevi");
Nabavka n = new Nabavka();
for (int i = 0; i < izabrane.size(); i++) {
System.out.println(izabrane.get(i).getNaziv());
NabavkaKorpaPK nkPK = new NabavkaKorpaPK();
nkPK.setIdNabavka(n.getIdNabavka());
nkPK.setIdNamirnica(izabrane.get(i).getIdNamirnica());
NabavkaKorpa nk = new NabavkaKorpa();
nk.setId(nkPK);
nk.setKolicina(brojevi.get(i));
nk.setUkupnaCena(izabrane.get(i).getCenaNamirnice() * brojevi.get(0));
izabrane.get(i).addNabavkaKorpa(nk);
n.addNabavkaKorpa(nk);
nabr.updateNamirnica(izabrane.get(i));
}
n.setDatumNabavke(new Date());
n.setUkupnaCena(n.getNabavkaKorpas().stream().map(k -> k.getUkupnaCena()).reduce(0.0,
(a, b) -> a + b));
n.setDobavljac(dobavljac);
dobavljac.addNabavka(n);
nabr.save(n);
return "uspehNabavka";
}
納巴夫卡.java:
@Entity
@NamedQuery(name="Nabavka.findAll", query="SELECT n FROM Nabavka n")
public class Nabavka implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int idNabavka;
@Temporal(TemporalType.TIMESTAMP)
private Date datumNabavke;
private double ukupnaCena;
//bi-directional many-to-one association to Dobavljac
@ManyToOne
@JoinColumn(name="idDobavljac")
private Dobavljac dobavljac;
//bi-directional many-to-one association to Menadzer
@ManyToOne
@JoinColumns({
@JoinColumn(name="idMenadzer", referencedColumnName="idMenadzer"),
@JoinColumn(name="idRadnik", referencedColumnName="idRadnik")
})
private Menadzer menadzer;
//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="idUser")
private User user;
//bi-directional many-to-one association to NabavkaKorpa
@OneToMany(mappedBy="nabavka", cascade={CascadeType.ALL})
private List<NabavkaKorpa> nabavkaKorpas = new ArrayList<NabavkaKorpa>();
public Nabavka() {
}
public int getIdNabavka() {
return this.idNabavka;
}
public void setIdNabavka(int idNabavka) {
this.idNabavka = idNabavka;
}
public Date getDatumNabavke() {
return this.datumNabavke;
}
public void setDatumNabavke(Date datumNabavke) {
this.datumNabavke = datumNabavke;
}
public double getUkupnaCena() {
return this.ukupnaCena;
}
public void setUkupnaCena(double ukupnaCena) {
this.ukupnaCena = ukupnaCena;
}
public Dobavljac getDobavljac() {
return this.dobavljac;
}
public void setDobavljac(Dobavljac dobavljac) {
this.dobavljac = dobavljac;
}
public Menadzer getMenadzer() {
return this.menadzer;
}
public void setMenadzer(Menadzer menadzer) {
this.menadzer = menadzer;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public List<NabavkaKorpa> getNabavkaKorpas() {
return this.nabavkaKorpas;
}
public void setNabavkaKorpas(List<NabavkaKorpa> nabavkaKorpas) {
this.nabavkaKorpas = nabavkaKorpas;
}
public NabavkaKorpa addNabavkaKorpa(NabavkaKorpa nabavkaKorpa) {
getNabavkaKorpas().add(nabavkaKorpa);
nabavkaKorpa.setNabavka(this);
return nabavkaKorpa;
}
public NabavkaKorpa removeNabavkaKorpa(NabavkaKorpa nabavkaKorpa) {
getNabavkaKorpas().remove(nabavkaKorpa);
nabavkaKorpa.setNabavka(null);
return nabavkaKorpa;
}
}
Namirnica.java:
@Entity
@NamedQuery(name="Namirnica.findAll", query="SELECT n FROM Namirnica n")
public class Namirnica implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int idNamirnica;
private double cenaNamirnice;
private String kolicina;
private String naziv;
private int stanje;
//bi-directional many-to-one association to NabavkaKorpa
@OneToMany(mappedBy="namirnica")
private List<NabavkaKorpa> nabavkaKorpas = new ArrayList<NabavkaKorpa>();
public Namirnica() {
}
public int getIdNamirnica() {
return this.idNamirnica;
}
public void setIdNamirnica(int idNamirnica) {
this.idNamirnica = idNamirnica;
}
public double getCenaNamirnice() {
return this.cenaNamirnice;
}
public void setCenaNamirnice(double cenaNamirnice) {
this.cenaNamirnice = cenaNamirnice;
}
public String getKolicina() {
return this.kolicina;
}
public void setKolicina(String kolicina) {
this.kolicina = kolicina;
}
public String getNaziv() {
return this.naziv;
}
public void setNaziv(String naziv) {
this.naziv = naziv;
}
public int getStanje() {
return this.stanje;
}
public void setStanje(int stanje) {
this.stanje = stanje;
}
public List<NabavkaKorpa> getNabavkaKorpas() {
return this.nabavkaKorpas;
}
public void setNabavkaKorpas(List<NabavkaKorpa> nabavkaKorpas) {
this.nabavkaKorpas = nabavkaKorpas;
}
public NabavkaKorpa addNabavkaKorpa(NabavkaKorpa nabavkaKorpa) {
getNabavkaKorpas().add(nabavkaKorpa);
nabavkaKorpa.setNamirnica(this);
return nabavkaKorpa;
}
public NabavkaKorpa removeNabavkaKorpa(NabavkaKorpa nabavkaKorpa) {
getNabavkaKorpas().remove(nabavkaKorpa);
nabavkaKorpa.setNamirnica(null);
return nabavkaKorpa;
}
}
NabavkaKorpa.java:
@Entity
@NamedQuery(name="NabavkaKorpa.findAll", query="SELECT n FROM NabavkaKorpa n")
public class NabavkaKorpa implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private NabavkaKorpaPK id;
private int kolicina;
private double ukupnaCena;
//bi-directional many-to-one association to Nabavka
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="idNabavka", insertable = false, updatable = false)
private Nabavka nabavka;
//bi-directional many-to-one association to Namirnica
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="idNamirnica", insertable = false, updatable = false)
private Namirnica namirnica;
public NabavkaKorpa() {
}
public NabavkaKorpaPK getId() {
return this.id;
}
public void setId(NabavkaKorpaPK id) {
this.id = id;
}
public int getKolicina() {
return this.kolicina;
}
public void setKolicina(int kolicina) {
this.kolicina = kolicina;
}
public double getUkupnaCena() {
return this.ukupnaCena;
}
public void setUkupnaCena(double ukupnaCena) {
this.ukupnaCena = ukupnaCena;
}
public Nabavka getNabavka() {
return this.nabavka;
}
public void setNabavka(Nabavka nabavka) {
this.nabavka = nabavka;
}
public Namirnica getNamirnica() {
return this.namirnica;
}
public void setNamirnica(Namirnica namirnica) {
this.namirnica = namirnica;
}
}
NabavkaKorpaPK.java:
@Embeddable
public class NabavkaKorpaPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(insertable=false, updatable=false)
private int idNamirnica;
@Column(insertable=false, updatable=false)
private int idNabavka;
public NabavkaKorpaPK() {
}
public int getIdNamirnica() {
return this.idNamirnica;
}
public void setIdNamirnica(int idNamirnica) {
this.idNamirnica = idNamirnica;
}
public int getIdNabavka() {
return this.idNabavka;
}
public void setIdNabavka(int idNabavka) {
this.idNabavka = idNabavka;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof NabavkaKorpaPK)) {
return false;
}
NabavkaKorpaPK castOther = (NabavkaKorpaPK)other;
return
(this.idNamirnica == castOther.idNamirnica)
&& (this.idNabavka == castOther.idNabavka);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.idNamirnica;
hash = hash * prime + this.idNabavka;
return hash;
}
}
NabavkaKorpaRepository.java:
public interface NabavkaKorpaRepository extends JpaRepository<NabavkaKorpa, NabavkaKorpaPK> {
}
NabavkaRepository.java:
public interface NabavkaRepository extends JpaRepository<Nabavka, Integer>, NabavkaRepoSpecific {
}
NabavkaRepoSpeicific.java
public interface NabavkaRepoSpecific {
public void updateNamirnica(Namirnica namirnica);
}
NabavkaRepoSpecificImpl.java:
@Repository
@Transactional
public class NabavkaRepoSpecificImpl implements NabavkaRepoSpecific {
@PersistenceContext
EntityManager em;
@Override
public void updateNamirnica(Namirnica namirnica) {
try {
em.merge(namirnica);
} catch (Exception e) {
e.printStackTrace();
}
}
}
NamirnicaRepository.java:
public interface NamirnicaRepository extends JpaRepository<Namirnica, Integer> {
}
例外:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: model.Namirnica.nabavkaKorpas, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:614) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:591) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.write(AbstractPersistentCollection.java:415) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:407) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at model.Namirnica.addNabavkaKorpa(Namirnica.java:85) ~[classes/:na]
at com.example.demo.controller.NabavkaController.sacuvajNabavku(NabavkaController.java:95) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.21.jar:5.3.21]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.21.jar:5.3.21]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.64.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.21.jar:5.3.21]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.64.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.21.jar:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1787) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.64.jar:9.0.64]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
編輯:我從一個會話中得到了 Namirnicas。 這是 GitHub鏈接。
錯誤的原因是您在流程的一個步驟(讓我們將其命名為A
)獲得列表List<Namirnica> izabrane
,但在第二步( B
)使用Namirinica
項目。
默認情況下,此列表是惰性的。 這意味着您只能在A
點訪問它(當@Transaction
/Persistent Context/Hibernate Session 打開時)。
@OneToMany(mappedBy="namirnica")
private List<NabavkaKorpa> nabavkaKorpas = new ArrayList<NabavkaKorpa>();
即使在B
點打開一個新事務也無濟於事,因為它將是另一個 Persistent context/Hibernate 會話(與A
點不同)。
您可以嘗試制作nabavkaKorpas
EAGER
,可能會有所幫助。 但是你有一個設計問題。
通則
永遠不要使用來自@OneToMany
部分的關聯集合。
怎么修
你必須保存一個新的NabavkaKorpa
,而不是Namirnica
。
NabavkaKorpa nabavka = new NabavkaKorpa();
nabavka.setNamirnica(namirnica);
nabavkaKorpaRepositiry.save(nabavka);
你甚至不需要Namirnica
來做到這一點。
對於休眠
Namirnica namirnica= new Namirnica();
namirnica.setId(namirnicaId);
NabavkaKorpa nabavka = new NabavkaKorpa();
nabavka.setNamirnica(namirnica);
nabavkaKorpaRepositiry.save(nabavka);
對於 Spring Data(沒有額外的查詢來從數據庫中獲取 Namirnica)
Namirnica namirnica= namirinicaRepositiry.getOne(namirnicaId);
NabavkaKorpa nabavka = new NabavkaKorpa();
nabavka.setNamirnica(namirnica);
nabavkaKorpaRepositiry.save(nabavka);
關於持久上下文的注釋
當你在方法上使用@Transactional
注解時,該方法內部不僅有一個打開的事務,而且還打開了Persistent Context/Hibernate Session。 所以這種在 Spring 中廣泛使用的@Transactional
方法有點混亂。
當 Persistent Context 打開時,Hibernate 會觀察對持久對象所做的所有更改,例如Namirnica
和NabavkaKorpa
,並嘗試將它們保存到數據庫中,因此您甚至不需要調用存儲庫的save()
方法(但我更喜歡顯式調用它)。 因此,在這種情況下,您可能可以從兩個方面保持關聯處於有效狀態: Namirnica
在列表中有NabavkaKorpa
並且NabavkaKorpa
指的是Namirnica
。 但通常我不會保留這些東西。
當 Persistent Context 關閉時,Hibernate 不會觀察更改,您不必將關聯保持在有效狀態。 當您調用存儲庫方法時,會為每個此類調用創建一個單獨的持久上下文。 並且所有這樣的調用都獨立於 Hibernate 的觀點。 您可以啟用 SQL 日志記錄並查看會發生什么。
所以你不需要做
izabrane.get(i).addNabavkaKorpa(nk);
只需與NabavkaKorpa
。
筆記
在這里有CascadeType.ALL
是一個非常糟糕的主意。
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="idNamirnica", insertable = false, updatable = false)
private Namirnica namirnica;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.