0

我正在使用 Hibernate 3.2.5 创建一个 Spring Web MVC 3.1.1 应用程序。我在 Netbeans 7.2 中开发,应用服务器是 GlassFish 3.1.2。数据库是Mysql 5.5。

我的问题是 subclass 没有预先加载@OneToMany,而另一个具有 a@OneToMany的类能够加载。此问题仅在 Glassfish 上出现:当我以完全相同的逻辑运行本地脚本时,没有问题。

相关的休眠配置:

<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>

其基本理念是美式橄榄球比赛。AGame包含几个GamePhases( Series, Kickoffs, Half Time, End Of Game);a Seriescontains Plays,它们被进一步细分。

GamePhase& 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(<- 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 中运行它时(请原谅脚本,我仍在学习 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>play 为空。如果我注释掉 <%-- series.getFirstPlay() --%>,代码可以正常工作并呈现良好。

据我所知,唯一的区别是@OneToManyinPlay指的是一个子类实体,而@OneToManyinGamePhase不是...

有任何想法吗?

4

2 回答 2

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 内容。

于 2013-02-12T16:31:14.233 回答
0

我认为您已经正确识别了问题。请记住,在获取您Game的 . 此时,它知道它将需要GamePhase. 你没有要求它获取一个子类,GamePhase所以通常它不会。因此,获得一切的连接Game通常永远不会包含来自Series.

(要么是那个,要么是因为你plays直接使用变量,而不是getPlays()在你的方法中使用。)

做到这一点的唯一方法是修复设计。例如,making 扮演了 every 的可选部分GamePhase。如何做得更优雅一点需要更多的思考。

于 2013-02-12T16:28:34.867 回答