我正在使用Hibernate 3.2.5创建Spring Web MVC 3.1.1应用程序。我正在开发Netbeans 7.2,应用服务器是GlassFish 3.1.2。数据库是Mysql 5.5。
我的问题是子类@OneToMany
没有急切的加载,而另一个@OneToMany
的类能够加载。这个问题仅出现在Glassfish上:当我运行具有完全相同逻辑的本地脚本时,没有问题。
相关的Hibernate配置:
<hibernate-configuration>
<session-factory>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="blagae.db.game.Game"/>
<mapping class="blagae.db.game.GamePhase"/>
<mapping class="blagae.db.game.Series"/>
<mapping class="blagae.db.play.Play"/>
</session-factory>
</hibernate-configuration>
基本思想是美式橄榄球比赛。 Game
包含多个GamePhases
(Series
,Kickoffs
,Half Time
,End Of Game
); Series
包含Plays
,它们是进一步的子类。
GamePhase
&amp; Game
(这些工作):
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class GamePhase implements Serializable {
@Id
@GeneratedValue
private int gamePhaseID;
@ManyToOne(fetch = FetchType.EAGER)
private Game game;
}
@Entity
public class Game implements Serializable {
@Id
@GeneratedValue
private int gameID;
@OneToMany(cascade=CascadeType.ALL, mappedBy="game", fetch=FetchType.EAGER)
private List<GamePhase> gamePhases = new ArrayList<GamePhase>();
public List<GamePhase> getGamePhases() {
return gamePhases;
}
public void setGamePhases(List<GamePhase> gamePhases) {
this.gamePhases = gamePhases;
}
public Series getFirstGamePhase() throws Exception {
if (gamePhases.isEmpty() || gamePhases == null) {
throw new Exception ("List<GamePhase> error");
}
return gamePhases.get(0);
}
}
Series
(&lt; - GamePhase
)和Play
:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Play implements Countable, Serializable {
@ManyToOne
private Series series;
}
@Entity
public class Series extends GamePhase implements Countable {
@OneToMany(cascade=CascadeType.ALL, mappedBy="series",fetch=FetchType.EAGER)
private List<Play> plays = new ArrayList<Play>();
public List<Play> getPlays() {
return plays;
}
public void setPlays(List<Play> plays) {
this.plays = plays;
}
public Play getFirstPlay() throws Exception {
if (plays.isEmpty() || plays == null) {
throw new Exception ("List<Play> error");
}
return plays.get(0);
}
}
当我在本地运行以下代码时,我得到了正常的响应:
Session session = SessionFactoryHelper.getSession();
try {
GamePhase gp = ((Game) session.get(Game.class, 1)).getFirstPlay();
System.out.println("GamePhaseID="+gp.getGamePhaseID());
Play play = ((Series) session.get(Series.class, 1)).getFirstPlay();
System.out.println("PlayID="+play.getPlayID());
}
catch (Exception e) {
e.printStackTrace(System.out);
}
响应:GamePhaseID = 1 PlayID = 1
当我在JSP中运行它时(请原谅scriptlets,我仍在学习JSTL的基础知识)。
<% Game game = (Game) request.getAttribute("game");
List<GamePhase> series = game.getDrives(); %>
<p> <%=game.getFirstGamePhase() %> </p>
<%for (GamePhase gamePhase : series) {
if (gamePhase.isSeries()) {
Series series = (Series) gamePhase;%>
<table>
<tr>
<td> <%= series.getGamePhaseID() %>
</td>
<td> Play <%= series.getFirstPlay() %>
</td>
</tr>
</table>
getFirstPlay()
方法失败,因为List<Play>
播放为空。如果我注释掉<%-- series.getFirstPlay() --%>
,则代码可以正常运行。
据我所知,唯一的区别是@OneToMany
中的Play
是指子类实体,而@OneToMany
中的GamePhase
则不是。 ..
有什么想法吗?
答案 0 :(得分:1)
问题在于铸造。
在工作示例中:
Play play = ((Series) session.get(Series.class, 1)).getFirstPlay();
在上面的场景中,您告诉Hibernate显式加载ID = 1的Series对象 - 因此它正确处理了预先加载的负载并加载了没有问题的播放。
然而,在第二个例子中:
for (GamePhase gamePhase : series) {
if (gamePhase.isSeries()) {
Series series = (Series) gamePhase;
这次Hibernate已经为你加载了GamePhase对象 - 当你将它转换为Series对象时,该方法是可用的,但显然Hibernate并不是那时急于在演员阵容上加载额外的Series东西。
答案 1 :(得分:0)
我认为你已经正确地发现了问题。请记住,在获取Game
时,Hibernate需要决定使用连接急切加载什么。此时,它知道它将需要GamePhase
中的所有内容。您没有要求它获取GamePhase
的子类,所以通常它不会。因此,Game
获取所有内容的联接通常不会包含Series
中的任何内容。
(或者是因为你直接使用plays
变量,而不是在你的方法中使用getPlays()
。)
唯一的方法是修复设计。例如,将播放作为每个GamePhase
的可选部分。如何做得更优雅需要更多的思考。