java - @OrderBy 被忽略

标签 java jpa eclipselink

我正在尝试从 OneToMany 关系中检索元素的有序列表,但似乎 @OrderBy 被简单地忽略了?!该应用程序使用 eclipselink 2.1。测试数据库是嵌入derby的。

以下是代码的相关(恕我直言)部分:

@Entity
public class VotingEntity implements Voting {

    ...

    /**
     * A voting has at least one question.
     */
    @OneToMany(mappedBy = "voting", targetEntity = QuestionEntity.class, cascade = { CascadeType.PERSIST,
            CascadeType.REMOVE, CascadeType.REFRESH })
    @OrderBy("groupNumber")
    private List<QuestionEntity> questions = new ArrayList<>();

    ...

}

问题实体:

@Entity
public class QuestionEntity implements Question {
    ... 
    /**
     * Could be used to group questions e.g. by pages.
     */
    private Integer groupNumber;
    ...
}

使用此代码我创建一个测试实体:

public class VotingInstance {

    private VotingEntity voting;

    public VotingInstance() {
        voting = new VotingEntity();
        //other setters
        ...     
        voting.setQuestions(createQuestions(voting));
    }

    public VotingEntity getVoting(){
        return voting;
    }

    /**
     * 
     * @return a list with test questions.
     */
    private List<QuestionEntity> createQuestions(VotingEntity voting) {
        List<QuestionEntity> result = new ArrayList<>();
        //question 1
        QuestionEntity q1 = new QuestionEntity();
        q1.setVoting(voting);
        q1.setGroupNumber(3);
        ...
        result.add(q1);
        //question 2
        QuestionEntity q2 = new QuestionEntity();
        q2.setGroupNumber(1);;
        q2.setVoting(voting);
        ...
        result.add(q2);
                //question 3
        QuestionEntity q3 = new QuestionEntity();
        q3.setVoting(voting);
        q3.setGroupNumber(2);
        ...
        result.add(q3);
        return result;

    }

    ...

}

这是实际测试:

public class PersistenceTest {

    @Rule
    public TemporaryFolder temp = new TemporaryFolder();

    EntityManager em;

    VotingEntity voting;

    @Before
    public void init() {
        voting = new VotingInstance().getVoting();
        em = new TestDbConfig(temp.getRoot().toString()).createEm();
        em.getTransaction().begin();
        em.persist(voting);
        em.getTransaction().commit();
        em.clear();
    }

    @After
    public void close() {
        em.close();
    }

    @Test
    public void checkVoting() {
        VotingEntity v = em.find(VotingEntity.class, voting.getID());
        for (Question q : v.getQuestions()) {
            System.out.println("q-id: " + q.getID() + " group: " + q.getGroupNumber());
        }
    }
}

输出按 id 排序(默认不带 OrderBY),但 q2 应该是第一个(orderNumer=1 )而 q1 应该是第二个?! 那么如何获取有序列表(我不需要保留数据库中的顺序,只有输出相关)。

更新:一些评论建议添加第三个问题并创建输出来检查实际的组号。我试过了,一切都很好。我更新了上面的代码。输出为:

q-id: 2 group: 3
q-id: 6 group: 1
q-id: 8 group: 2

最佳答案

根据 http://docs.oracle.com/javaee/5/api/javax/persistence/OrderBy.html 、OrderBy 仅在检索关联时对 QuestionEntity 实例进行排序。缺少的一点是,您似乎正在创建 VotingEntity 并且可能同时重新创建问题列表 - JPA 仅在从数据库返回时设置顺序。由应用程序来维护它。

尝试调用 em.refresh(v) 看看我的意思。这应该会导致从数据库刷新集合。

您遇到的问题是 JPA 允许二级缓存。因此,当您使用无序列表创建 VotingEntity 时,它会无序地保留在缓存中,并且不会从数据库中获取。为了保证顺序,应用程序需要始终维护它,或者在需要重新断言顺序时刷新它(和/或清除缓存)。

关于java - @OrderBy 被忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22039321/

相关文章:

java - JPA - 几分钟后与数据库的连接超时

java - JPA2 : create-or-extend-tables is not extending existing table with new column

java - Eclipse:无法加载 JNI 共享库“C:\Program Files(x86)\Java\jdk1.7.0_15\bin\..\jre\bin\client\jvm.dll

java - 如何仅使用 java 将 mp4 文件转换为 webm?

java - 为什么可以在循环中创建具有相同变量名的线程对象?

java - 如何为 div 和类创建的结账创建 xpath

java - @javax.persistence.Column(可更新=假)

java - 在java中选择查询(JPA)

java - Hibernate with SQLite 无法在数据库创建后第二次运行应用程序

java - EntityManagerFactory 中实体管理器的正确使用