Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA multiselect在联接返回值中返回null_Java_Hibernate_Jpa - Fatal编程技术网

Java JPA multiselect在联接返回值中返回null

Java JPA multiselect在联接返回值中返回null,java,hibernate,jpa,Java,Hibernate,Jpa,我的简化模型是: 玩家,可以玩游戏 游戏,玩家可以玩多次 得分玩家在玩给定游戏时收到 在我的实体映射中,Game和Score之间的关系是双向的,但是Player没有映射其所有Score的集合,只有Score=>Player关系。我的JPA提供程序是Hibernate,我的关系映射使用默认的FetchType(也就是说,FetchType没有显式的值,可能使用lazy,因为这是Hibernate的默认值,尽管JPA标准是这样的) 现在我想计算每个玩家p玩游戏g的次数,忽略玩过几次的玩家,我提出

我的简化模型是:

  • 玩家
    ,可以玩游戏
  • 游戏
    ,玩家可以玩多次
  • 得分
    玩家在玩给定游戏时收到
在我的实体映射中,
Game
Score
之间的关系是双向的,但是
Player
没有映射其所有
Score
的集合,只有
Score=>Player
关系。我的JPA提供程序是Hibernate,我的关系映射使用默认的
FetchType
(也就是说,
FetchType
没有显式的值,可能使用lazy,因为这是Hibernate的默认值,尽管JPA标准是这样的)

现在我想计算每个玩家p玩游戏g的次数,忽略玩过几次的玩家,我提出了以下查询:

SELECT p, g, COUNT(s.id)
FROM Score s JOIN 
     s.game g JOIN
     s.player p
WHERE *some additional filtering criteria, like games not being private etc*
GROUP BY p, g 
HAVING COUNT(s.id) >= :minimumGamesToQualify
当我运行以下代码时:

String strQuery = ...query above...;
Query query = em.createQuery(strQuery);
query.setParameter("criteriaParam", criteriaValue);
List result = query.getResultList();

返回的列表(如预期)包含
对象[]
的行,但
p
g
的返回值总是
null
(但计数计算正确且具有预期值)。但当我将查询的第一行更改为
SELECT p.id、g.id、COUNT(s.id)
时,返回的行包含
p
g
的预期id。 我知道这可能是因为懒散地获取引用,但是我如何强制查询检索
p
g
,尽管被映射为懒散?我可以用
JOIN FETCH
以某种方式完成吗

编辑:简化映射和查询调用(删除了IMO与问题无关的部分):

@实体
@表(name=“\”分数\”)
公共类分数扩展了抽象实体{
私有字符串名称;
私人日期:年月日;
公共分数(){}
@基本公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
@基本公共日期getScored_on(){return scored_on;}
公共无效设置得分日期{this.scored\u on=scored\u on;}
私人游戏;
@许多酮
@JoinColumn(name=“game\u id”,referencedColumnName=“id”)
公共游戏getGame(){return Game;}
public void setGame(Game Game){this.Game=Game;}
私人玩家;
@许多酮
@JoinColumn(name=“player\u id”,referencedColumnName=“id”)
公共播放器getPlayer(){return Player;}
public void setPlayer(Player){this.Player=Player;}
}
@实体
@表(name=“\”Games\”)
@XmlRootElement
公共类博弈扩展抽象实体{
私有字符串名称;
@基本公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
公共游戏(){}
私有列表分数=新的ArrayList();
@XmlTransient
@OneToMany(mappedBy=“游戏”)
公共列表getScores(){return scores;}
公共无效设置分数(列出分数){this.scores=scores;}
}
@实体
@表(name=“\”Players\”)
公共类播放器扩展了抽象实体{
私有字符串名;
私有字符串lastname;
私人字符串电子邮件;
公共播放器(){}
@基本公共字符串getFirstname(){return firstname;}
@基本公共字符串getLastname(){return lastname;}
@基本公共字符串getEmail(){return email;}
public void setFirstname(字符串firstname){this.firstname=firstname;}
public void setLastname(字符串lastname){this.lastname=lastname;}
public void setEmail(字符串email){this.email=email;}
}
String STRRELEVENTGAMESQUERY=“从分数s中选择p,g,计数(s.Id)加入s.game g加入s.player p,其中s.scored_on=:最小游戏显示”;
TypedQuery queryRelevantGames=em.createQuery(strRelevantGamesQuery,Object[].class);
queryRelevantGames.setParameter(“minimumGamesPlayes”,5L);
setParameter(“scoredBefore”,summaryDate);
List resultreelevantGames=queryreliantGames.getResultList();
//ResultTreeLevantGames是一个对象列表[3]。所有行[0]和行[1]对象均为空,行[2]包含正确计算的计数。
//当我将查询更改为:
//String STRRELEVENTGAMESQUERY=“从中选择p.Id、g.Id、计数(s.Id)。。。
//那么所有行[0]和行[1]都包含正确的ID

p
g
的值永远不应该是
null
-您能给我们看一个示例代码吗?@MaciejDobrowolski添加了映射和查询调用。我用您的映射创建了一个项目,用示例数据填充数据库,结果数组不包含null值,请尝试升级hibernate/spring(如果使用)
p
g
的版本值永远不应该是
null
-您能给我们看一个示例代码吗?@MaciejDobrowolski添加了映射和查询调用。我用您的映射创建了一个项目,用示例数据填充数据库,结果数组不包含null值,请尝试升级hibernate/spring(如果使用)版本
@Entity
@Table(name = "\"Scores\"")
public class Score extends AbstractEntity {

    private String name;
    private Date scored_on;

    public Score() { }

    @Basic public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    @Basic public Date getScored_on() { return scored_on; }
    public void setScored_on(Date scored_on) { this.scored_on = scored_on; }

    private Game game;
    @ManyToOne
    @JoinColumn(name="game_id", referencedColumnName="id")
    public Game getGame() { return game; }
    public void setGame(Game game) { this.game = game; }

    private Player player;
    @ManyToOne
    @JoinColumn(name="player_id", referencedColumnName="id")
    public Player getPlayer() { return player; }
    public void setPlayer(Player player) { this.player = player; }
}

@Entity
@Table(name="\"Games\"")
@XmlRootElement
public class Game extends AbstractEntity {

    private String name;
    @Basic public String getName() { return name; }
    public void setName (String  name) { this.name = name; }

    public Game() {    }

    private List<Score> scores = new ArrayList<Score>();

    @XmlTransient
    @OneToMany(mappedBy="game")
    public List<Score> getScores() { return scores; }
    public void setScores(List<Score> scores) { this.scores = scores; }
}

@Entity
@Table(name="\"Players\"")
public class Player extends AbstractEntity {

    private String firstname;
    private String lastname;
    private String email;

    public Player() { }

    @Basic public String getFirstname() { return firstname; }
    @Basic public String getLastname()  { return lastname; }
    @Basic public String getEmail()     { return email; }

    public void setFirstname(String firstname) { this.firstname = firstname; }
    public void setLastname(String lastname)   { this.lastname = lastname; }
    public void setEmail(String email)         { this.email = email; }

}

String strRelevantGamesQuery = "SELECT p, g, COUNT(s.Id) FROM Score s JOIN s.game g JOIN s.player p WHERE s.scored_on <= :scoredBefore GROUP BY p, g HAVING COUNT(s.Id) >= :minimumGamesPlayes";
TypedQuery<Object[]> queryRelevantGames = em.createQuery(strRelevantGamesQuery, Object[].class);
queryRelevantGames.setParameter("minimumGamesPlayes", 5L);
queryRelevantGames.setParameter("scoredBefore", summaryDate);
List<Object[]> resultRelevantGames = queryRelevantGames.getResultList();

//resultRelevantGames is a list of Object[3]. All row[0] and row[1] objects are null, row[2] contains correctly calculated counts.
//When I change query to: 
//    String strRelevantGamesQuery = "SELECT p.Id, g.Id, COUNT(s.Id) FROM...
//then all row[0] and row[1] contain correct IDs