如何按给定条件过滤@OneToMany集合的大小

时间:2015-04-24 10:56:25

标签: java mysql spring hibernate jpa

看看这个简单的例子:

@Entity
@Table(name = "message")
public class Message implements Serializable {

    @Id
    @GeneratedValue
    private Long              id;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn
    private User              author;

    @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
    private Set<Rating>       ratings;

    [...]
}

有没有办法通过过滤集合元素来限制ratings的大小。我只想加载不超过30天的评分。

通过这种方式我从数据库加载消息

public Message getMessageById(Serializable id) {
    Session session = _sessionFactory.getCurrentSession();
    return session.get(Message.class, id);
}

3 个答案:

答案 0 :(得分:3)

最终它有效。

解决方案:

@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
@Where(clause = "DATEDIFF(NOW(), date) <= 30")
private Set<Rating>       ratings;

来自Mysql docs

  

DATEDIFF()返回expr1 - expr2,表示为从一个日期到另一个日期的值天数。 expr1和expr2是日期或日期和时间表达式

  • 我也尝试了Vlad Mihalcea的解决方案但是异常:

      

    引起:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:SQL语法中有错误;检查与您的MySQL服务器版本对应的手册,以获得正确的语法,以便在&lt; 30; rating1_.DAY)和ratings_.message_id = 63&#39;附近使用。在第1行

  • StanislavL的解决方案有效,但只有在您激活过滤器时才会起作用:

    Session session = sessionFactory.getCurrentSession();
    Filter filter   = session.enableFilter("minAge");
    [...]
    session.disableFilter("minAge");
    

使用@Where注释更简单,因为它不需要激活。

答案 1 :(得分:1)

将@Filter注释添加到

@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
private Set<Rating>       ratings;

喜欢这个

@FilterDef(name="minAge", parameters=@ParamDef( name="age", type="integer" ) )
@Filters( {
    @Filter(name="minAge", condition=":age<= 30")
} )

查看更多here

答案 2 :(得分:1)

您需要使用@Where注释:

@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = { 
    CascadeType.PERSIST, 
    CascadeType.MERGE, 
    CascadeType.REMOVE 
})
@Where("time_created < NOW() - INTERVAL 30 DAY")
private Set<Rating> ratings = new HashSet<>();