0

Hibernate3.2.5を使用してSpringWebMVC3.1.1アプリケーションを作成しています。私はNetbeans7.2で開発していますが、アプリケーションサーバーはGlassFish3.1.2です。データベースはMysql5.5です。

私の問題は、サブクラスの積極的な読み込みがないのに対し、a@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>

基本的な考え方は、アメリカンフットボールの試合です。AGameにはいくつかの(GamePhases、、、、Series)が含まれています。aには、さらにサブクラス化されたが含まれます。KickoffsHalf TimeEnd Of GameSeriesPlays

GamePhaseGame(これらの作品):

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

再生がnullであるため、getFirstPlay()メソッドは失敗します。List<Play>コメントアウトする <%-- series.getFirstPlay() --%>と、コードは機能し、うまくレンダリングされます。

私が見る限り、唯一の違いは、@OneToManyinPlayがサブクラス化されたエンティティを参照しているのに対し、@OneToManyinはそうでGamePhaseはないということです...

何か案は?

4

2 に答える 2

1

問題はキャスティングです。

作業例では:

Play play = ((Series) session.get(Series.class, 1)).getFirstPlay();

上記のシナリオでは、ID = 1のSeriesオブジェクトを明示的にロードするようにHibernateに指示しているため、熱心なロードを正しく処理し、再生を問題なくロードします。

ただし、2番目の例では:

for (GamePhase gamePhase : series) {
    if (gamePhase.isSeries()) { 
        Series series = (Series) gamePhase;

今回、HibernateはGamePhaseオブジェクトをロードしました-それをSeriesオブジェクトにキャストすると、メソッドは使用可能ですが、明らかにHibernateはその時点でキャストに追加のSeriesのものをロードすることに熱心ではありません。

于 2013-02-12T16:31:14.233 に答える
0

あなたは問題を正しく特定したと思います。をフェッチするときGame、Hibernateは結合を使用して何を熱心にロードするかを決定する必要があることを忘れないでください。この時点で、のすべてが必要になることがわかりますGamePhase。のサブクラスをフェッチするように要求しなかったGamePhaseため、通常はフェッチしません。したがって、すべてを取得する結合にGameは、通常、からの何かが含まれることはありませんSeries

(それとも、メソッドplaysで使用するのではなく、変数を直接使用するためですgetPlays()。)

これを行う唯一の方法は、デザインを修正することです。たとえば、makeはすべてののオプションの部分を果たしますGamePhase。それをもう少しエレガントにする方法は、もう少し考える必要があります。

于 2013-02-12T16:28:34.867 に答える