我正在试着编写一个restapi。我的数据库充满了数据(所考虑的表大约有90000行)。我想选择一些数据(大约500个)。为了提高性能,我希望使用多线程。如果没有线程,一切都可以工作,但是如果我使用threadpoolexecutor来使用线程,并且在所有线程完成后,我希望将获取的行列表作为dto返回给控制器,我会得到异常:
org.hibernate.LazyInitializationException: could not initialize proxy [com.ghlabs.betpredictorapi.entity.Team#3] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:170) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:310) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at com.ghlabs.betpredictorapi.entity.Team$HibernateProxy$Be4OggaP.getAwayTeamMatches(Unknown Source) ~[classes/:na]
at jdk.internal.reflect.GeneratedMethodAccessor96.invoke(Unknown Source) ~[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:566) ~[na:na]
at org.modelmapper.internal.PropertyInfoImpl$MethodAccessor.getValue(PropertyInfoImpl.java:101) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.internal.MappingEngineImpl.resolveSourceValue(MappingEngineImpl.java:197) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:171) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:152) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:106) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:72) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:573) ~[modelmapper-2.3.8.jar:na]
at org.modelmapper.ModelMapper.map(ModelMapper.java:406) ~[modelmapper-2.3.8.jar:na]
at com.ghlabs.betpredictorapi.service.MatchService.convertToMatchDTO(MatchService.java:110) ~[classes/:na]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
at com.ghlabs.betpredictorapi.service.MatchService.findByLeagueAndSeasonRange(MatchService.java:89) ~[classes/:na]
at com.ghlabs.betpredictorapi.controller.CalculationController.calculateMatch(CalculationController.java:55) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[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:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.1.jar:5.3.1]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.1.jar:5.3.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.39.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
以下是im使用的函数(im调用findbyleagueandseasonrange函数):
public List<MatchDTO> findByLeagueAndSeasonRange(Long leagueId, int minSeasonYearEnd, int maxSeasonYearEnd) {
ExecutorService es = Executors.newFixedThreadPool(10);
Pageable pageable = PageRequest.of(0,50, Sort.by("matchDate").descending());
Page<Match> page = matchRepository.findByLeagueAndSeasonRange(leagueId, minSeasonYearEnd, maxSeasonYearEnd, pageable);
List<Match> matches = new ArrayList<>(page.getContent());
logger.info("---- Total Pages: " + page.getTotalPages());
logger.info("Page " + 1 + " - Elements: " + page.getNumberOfElements());
for (int i = 1; i < page.getTotalPages(); i++) {
int finalI = i;
Callable<List<Match>> callable = () -> {
Pageable pageable2 = PageRequest.of(finalI,50);
Page<Match> p = matchRepository.findByLeagueAndSeasonRange(leagueId, minSeasonYearEnd, maxSeasonYearEnd, pageable2);
logger.info("Page " + (finalI + 1)+ " - Elements: " + p.getNumberOfElements());
return p.getContent();
};
Future<List<Match>> future = es.submit(callable);
try {
List<Match> futureMatches = future.get();
matches.addAll(futureMatches);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
shutdownAndAwaitTermination(es);
logger.info(matches.size() + " matches fetched from database.");
return matches.stream()
.map(this::convertToMatchDTO)
.collect(Collectors.toList());
}
private void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown();
try {
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(30, TimeUnit.SECONDS))
logger.error("Pool did not terminate");
}
} catch (InterruptedException ie) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
private MatchDTO convertToMatchDTO(Match match) {
modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.LOOSE);
return modelMapper
.map(match, MatchDTO.class);
}
例外情况中被考虑的实体如下:
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Team implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String teamName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_league", referencedColumnName = "id", nullable = false)
private League league;
@OneToMany(mappedBy="homeTeam")
List<Match> homeTeamMatches;
@OneToMany(mappedBy="awayTeam")
List<Match> awayTeamMatches;
@Column(name = "created_at", nullable = false, updatable = false)
private Date createdAt;
@Column(name = "updated_at", nullable = false)
private Date updatedAt;
public Team(String teamName, League league) {
this.teamName = teamName;
this.league = league;
}
@PrePersist
private void createdAt() {
this.createdAt = new Date();
this.updatedAt = new Date();
}
@PreUpdate
private void updatedAt() {
this.updatedAt = new Date();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Team team = (Team) o;
return id.equals(team.id) &&
teamName.equals(team.teamName);
}
@Override
public int hashCode() {
return Objects.hash(id, teamName);
}
@Override
public String toString() {
return "Team{" +
"id=" + id +
", teamName='" + teamName + '\'' +
", league=" + league +
", homeTeamMatches=" + homeTeamMatches +
", awayTeamMatches=" + awayTeamMatches +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
'}';
}
}
这是我从数据库得到的实体:
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "matches")
public class Match {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date matchDate;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_homeTeam", referencedColumnName = "id", nullable = false)
private Team homeTeam;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_awayTeam", referencedColumnName = "id", nullable = false)
private Team awayTeam;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_league", referencedColumnName = "id", nullable = false)
private League league;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_season", referencedColumnName = "id", nullable = false)
private Season season;
private int homeTeamFTGoals;
private int awayTeamFTGoals;
private int homeTeamHTGoals;
private int awayTeamHTGoals;
private boolean homeTeamFTWins;
private boolean awayTeamFTWins;
private boolean homeTeamHTWins;
private boolean awayTeamHTWins;
private boolean drawFT;
private boolean drawHT;
private int homeTeamShots;
private int awayTeamShots;
private int homeTeamShotsOnTarget;
private int awayTeamShotsOnTarget;
private int homeTeamHitWoodWork;
private int awayTeamHitWoordWork;
private int homeTeamCorners;
private int awayTeamCorners;
private int homeTeamFoulsCommitted;
private int awayTeamFouldCommitted;
private int homeTeamFreekicksConceeded;
private int awayTeamFreekicksConceeded;
private int homeTeamOffsides;
private int awayTeamOffsides;
private int homeTeamYellowCards;
private int awayTeamYellowCards;
private int homeTeamRedCards;
private int awayTeamRedCards;
@Column(name = "created_at", nullable = false, updatable = false)
private Date createdAt;
@Column(name = "updated_at", nullable = false)
private Date updatedAt;
public Match(League league, Season season, Date matchDate, Team homeTeam, Team awayTeam, int fthg, int ftag, int hthg, int htag, boolean b, boolean b1, boolean b2, boolean b3, boolean b4, boolean b5, int hs, int as, int hst, int ast, int hhw, int ahw, int hc, int ac, int hf, int af, int hfkc, int afkc, int ho, int ao, int hy, int ay, int hr, int ar) {
this.league = league;
this.season = season;
this.matchDate = matchDate;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
this.homeTeamFTGoals = fthg;
this.awayTeamFTGoals = ftag;
this.homeTeamHTGoals = hthg;
this.awayTeamHTGoals = htag;
this.homeTeamFTWins = b;
this.awayTeamFTWins = b1;
this.homeTeamHTWins = b2;
this.awayTeamHTWins = b3;
this.drawFT = b4;
this.drawHT = b5;
this.homeTeamShots = hs;
this.awayTeamShots = as;
this.homeTeamShotsOnTarget = hst;
this.awayTeamShotsOnTarget = ast;
this.homeTeamHitWoodWork = hhw;
this.awayTeamHitWoordWork = ahw;
this.homeTeamCorners = hc;
this.awayTeamCorners = ac;
this.homeTeamFoulsCommitted = hf;
this.awayTeamFouldCommitted = af;
this.homeTeamFreekicksConceeded = hfkc;
this.awayTeamFreekicksConceeded = afkc;
this.homeTeamOffsides = ho;
this.awayTeamOffsides = ao;
this.homeTeamYellowCards = hy;
this.awayTeamYellowCards = ay;
this.homeTeamRedCards = hr;
this.awayTeamRedCards = ar;
}
@PrePersist
private void createdAt() {
this.createdAt = new Date();
this.updatedAt = new Date();
}
@PreUpdate
private void updatedAt() {
this.updatedAt = new Date();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Match match = (Match) o;
return id.equals(match.id) &&
matchDate.equals(match.matchDate) &&
homeTeam.equals(match.homeTeam) &&
awayTeam.equals(match.awayTeam) &&
Objects.equals(league, match.league) &&
Objects.equals(season, match.season);
}
@Override
public int hashCode() {
return Objects.hash(id, matchDate, homeTeam, awayTeam, league, season);
}
@Override
public String toString() {
return "Match{" +
"id=" + id +
", matchDate=" + matchDate +
", homeTeam=" + homeTeam +
", awayTeam=" + awayTeam +
", league=" + league +
", season=" + season +
'}';
}
}
有人能帮我吗?
暂无答案!
目前还没有任何答案,快来回答吧!