Java JPA:选择随机行

Java JPA:选择随机行,java,jpa,jpql,named-query,Java,Jpa,Jpql,Named Query,这是我的JPA实体 @Entity @NamedQueries({ @NamedQuery(name = "Question.randQuestion", query = "SELECT q FROM Question AS q ORDER BY RANDOM") }) @Table(name = "questions") public class Question implements Serializable { ..... } 问题是: eclipse为这个n

这是我的JPA实体

@Entity
@NamedQueries({  
        @NamedQuery(name = "Question.randQuestion", query = "SELECT q FROM Question AS q ORDER BY     RANDOM")
})
@Table(name = "questions")
public class Question implements Serializable {
.....
}
问题是:

eclipse为这个namedQuery提供了一个错误。它说: “FROM子句中未定义标识变量“RANDOM”

我也尝试使用RAND()代替RANDOM和NEWID()


谢谢。

据我所知,您希望从表中选择随机问题。您更希望使用WHERE子句,从代码中提供一些参数,如:

SELECT q FROM Question AS q WHERE id = :id
然后,在创建查询的代码中,必须生成要选择的随机id:

query.setParam("id", getRandomId());
要获取随机id,您可能需要从DB查询行数,并使用
java.util.random.nextInt(rowsCount)
(当然,如果所有id都存在的话)


顺便说一句,这里也描述了类似的情况:

要获得一个随机行,首先获取全部问题的列表,然后获取任意一个

public Question  getRandomQuestion(EntityManager em) {
  Query countQuery = em.createNativeQuery("select count(*) from Question");
  long count = (Long)countQuery.getSingleResult();

  Random random = new Random();
  int number = random.nextInt((int)count);

  Query selectQuery = em.createQuery("select q from Question q");
  selectQuery.setFirstResult(number);
  selectQuery.setMaxResults(1);
  return (Question)selectQuery.getSingleResult();
}

注意:在多次调用方法时,您可能需要实现一个逻辑以避免重复。

我必须解决这个问题的一个特定案例,在这个案例中,我必须从一组符合特定输入条件的记录中选择随机记录。解决方案还必须支持限制。我在下面从假设开始描述我的解决方案

假设:

  • 给定一组条件作为输入,可以计算与选择条件匹配的记录数,如
    org.springframework.data.querydsl.QueryDslPredicateExecutor.count(谓词谓词)
    方法所支持的

  • 页面没有索引

  • 可以请求由
    org.springframework.data.domain.PageRequest(int-page,int-size)
    方法支持的特定页面

算法

  • 统计与输入条件匹配的所有记录

  • 根据计数和指定的限制计算总页数

  • 生成范围为[0,总页数]的随机页面索引

  • 请求具有上一步中生成的索引的页面

  • 在返回的页面中无序移动元素

  • 代码

    Long totalRecords = someRepository.count(somePredicate);
    Long totalPages =
        (totalRecords % someLimit == 0)
            ? (totalRecords / someLimit)
            : ((totalRecords / someLimit) + 1);
    int pageIndex = (int) (Math.random() * totalPages);
    
    PageRequest pageRequest = new PageRequest(pageIndex, someLimit);
    Page<T> somePage = someRepository.findAll(somePredicate, pageRequest);
    List<T> someList;
    if (somePage.getTotalElements() > 0) {
      someList = new ArrayList<>(somePage.getContent());
    } else {
      someList = new ArrayList<>();
    }
    
    Collections.shuffle(someList);
    
    longtotalrecords=someRepository.count(somePredicate);
    长总页数=
    (totalRecords%someLimit==0)
    ?(总记录/某些限制)
    :((totalRecords/someLimit)+1);
    int pageIndex=(int)(Math.random()*totalPages);
    PageRequest PageRequest=新的PageRequest(pageIndex,someLimit);
    Page somePage=someRepository.findAll(somePredicate,pageRequest);
    列出一些清单;
    if(somePage.getTotalElements()>0){
    someList=newArrayList(somePage.getContent());
    }否则{
    someList=newArrayList();
    }
    集合。洗牌(someList);
    

    第二步是确保页面中的记录也是随机的。此解决方案的一般情况是没有标准,因此必须使用无
    谓词调用
    count()
    ,从而获得表中所有行的计数。

    从问题中选择q作为q ORDER BY RANDOM()
    但它将以随机顺序返回所有行。如果我理解正确,则可能重复,您给出了随机化1个问题的解决方案。但如果我想要一些,我尝试使用setMaxResult(4)从DB获取4个问题,但它以与DB相同的顺序给我4个问题(假设第一个被随机分配的问题是第5个问题,DB的其他3个问题是第6、7和8个问题)但我希望其他3个问题也被随机分配。最好的方法是什么?Thanks@user3168286您需要调用此方法n次以获得n个随机问题。此外,您可能需要实现一个逻辑来跳过重复,因为随机数是used@Mr.Pichler你在否决投票前试过吗?我回答说假设ID从(1,2,3…n).@Mr.Pichler在选择查询中的持久化发生在哪里。@vels4j我删除了我的评论。很抱歉进行了否决表决。如果您编辑您的问题,我可以将其删除。结果是我否决了您的答案,而不是我想要的上一个答案。此外,我的评论是针对另一个答案的。这只适用于ID在上连续的情况数据库。除了@JamesNewman提到的之外,可以返回
    0
    。最大值是独占的,因此您应该在随机结果中添加1。构造函数
    PageRequest PageRequest=new PageRequest(pageIndex,someLimit)
    已弃用,因此我们可以使用
    PageRequest PageRequest=PageRequest.of(pageIndex,someLimit)