SQL Developer Client和JPA / Hibernate结果之间的结果不同LAST_VALUE

时间:2014-02-19 21:34:23

标签: java hibernate jpa oracle11g

**问题更新

因此,下面描述的问题似乎不是查询或使用LAST_VALUE / PARTITION。我一直用JUnit用JPA测试这个新查询。在我的JUnit设置中,我有以下设置/拆解...

@Before
public void init() {
    myDao.setEntityManager(entityManager);
    entityManager.getTransaction().begin();
    populateTestData();
}   

@After
public void cleanUp() {
    entityManager.flush();
    entityManager.getTransaction().rollback();
}

private void populateTestData() {
    for(MyModelObject modelObject: DataStore.getAllDummyData()){
        myDao.persist(modelObject);
    }
}

如果我为 MyModelObject 创建一个新的但相同的类,请说 MyModelObject2 并使用 MyModelObject 保留,但使用 MyModelObject2进行检索,然后一切正常,我得到了我期望的查询结果。

显然我不希望有一个重复的类作为hack用于此,但这使我相信时髦的结果是由于我持续在持久化上下文中管理的对象在测试的生命周期中。如果我使用persist()或merge()并不重要,我会得到相同的结果。

有人可以建议我如何妥善处理这种情况吗?看来我需要避免托管对象看到所需的实际查询结果。在检索结果之前,可能需要首先提交数据?我怎样才能修改上面的JUnit init()和cleanUp()以允许我插入一些虚拟数据,运行不受事务中托管对象影响的测试,然后清理/回滚虚拟数据?


问题

我在SQL Developer Lite中测试用于创建hibernate本机查询的查询。我遇到的问题是当我在SQL Developer Tool中运行查询时,它可以像我期望的那样工作。但是通过Hibernate运行相同的查询会给我带来不同的结果。这几乎就像Hibernate版本不关心LAST_VALUE函数和/或PARTITION BY子句。

这是我在SQL Dev Lite

中运行的查询
SELECT
LAST_VALUE(serviceid) OVER (PARTITION BY logid ORDER BY serviceid RANGE 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) serviceid, 
logid, type, startdate, stopdate, agent, userid, lastupdated
FROM (
  SELECT * FROM SERVICELOGS WHERE logid IN ('2314-4523-8897-0923-8734') 
  ORDER BY lastupdatedtime DESC
) 
ORDER BY lastupdatedtime DESC

这是结果

您将在此示例中看到已为所有行填充了serviceid ...如果我删除了LAST_VALUE和PARTITION,那么它将返回与我下一个示例中的结果集相同的结果集。

**************************************************
|     ServiceID     |         LogID          | ...
**************************************************
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..

现在这里是来自休眠方的查询...

这里我只是在帮助器类中构建查询字符串..

private static final StringBuilder BASIC_QUERY_STRING = new StringBuilder();

static {
  BASIC_QUERY_STRING
  .append(" SELECT ")
  .append(" LAST_VALUE(serviceid) OVER (PARTITION BY logid ORDER BY serviceid RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) serviceid,")
  .append(OTHER_FIELD_NAMES)
  .append(" FROM ( SELECT * FROM SERVICELOGS WHERE logid IN ('2314-4523-8897-0923-87') ORDER BY lastupdated DESC) ORDER BY lastupdated DESC")
}

这是我执行查询的DAO方法..

@Override
@Transactional(readOnly = true)
public Collection<MyModelObject> runQuery(final MyOptionalParams queryParams) throws IllegalArgumentException {
    List<MyModelObject> result = getJpaTemplate().execute(new JpaCallback<List<MyModelObject>>() {
        @Override
        @SuppressWarnings("unchecked")
        public List<MyModelObject> doInJpa(final EntityManager em) throws PersistenceException {
            Query query = MyQueryFactory.createQueryWithParams(queryParams, em); 
            return query.getResultList();
        }
    });
    return result;
}

在MyQueryFactory.createQueryWithParams(queryParams,em)

这基本上是正在发生的事情,还有其他一些用于填充params的东西,但是对于直接查询没有任何影响,只有在我作为测试运行的查询字符串中硬编码的任何参数...

Query query = em.createNativeQuery(BASIC_QUERY_STRING.toString(), MY_JOIN_MAPPING);

奇怪的结果......

现在注意serviceid列,好像我没有使用LAST_VALUE和PARTITION。 我使用last_value和分区的目的是获得一个没有serviceid的0的结果集。不幸的是,我没有足够的空间来显示更多的表数据,但是还有一个我要订购的最后一列,这是一个基本的时间戳,想法是从各个行“冒泡”数据此表然后选择顶行,每行的所有数据汇总为一个结果。我需要我的serviceid根据带有logid的分区填写该列。

**************************************************
|     ServiceID     |         LogID          | ...
**************************************************
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 0                 | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..
| 1234567           | 2314-4523-8897-0923-87 | ..

摘要

我知道有数百种不同的方法来分析和排序数据,我的一个大问题是,为什么这两个查询在同一个查询时表现不同!? ..显而易见的是,一个在SQL Developer中运行,另一个在Hibernate中运行。那么为什么hibernate似乎不能处理LAST_VALUE / PARTITION BY ???我没有看到任何错误,我只是没有看到我希望看到的结果基于在SQL Developer中运行相同的查询..

旁注

只是为了看看hibernate是否忽略了last_value /分区,我故意弄乱了last_value和分区以查看它是否完全看到它......

示例:取代此..

LAST_VALUE(serviceid) OVER (PARTITION BY logid ORDER BY serviceid RANGE 
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) serviceid, ...

我做了类似的事情..

LAST_VALUE(serviceid) OVER (PARTITION BY logid ORDER BY serviceid RANGE 
BETWEEN *UNBOUND* PRECEDING AND *UNBOUND* FOLLOWING) serviceid, ...

当然这确实会产生错误......仅供参考我只是在上面编辑了“*”来表示,但是我刚刚删除了UNBOUNDED的“ed”以查看它是否使用它,它看起来像hibernate或介于两者之间的东西并不关心使用它。

附加备注

这是来自我的persistance.xml的一些道具..我没有连接或运行任何查询的问题,我只是不明白为什么我没有看到与我在SQL Developer中的hibernate相同的结果..

<property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>

1 个答案:

答案 0 :(得分:0)

事实证明,该问题与运行本机查询和使用函数LAST_VALUE和PARTITION BY无关。结果是数据,以及看似缓存来自hibernate的数据。这演变成了一个新问题Hibernate with JPA 1.0 Caching Issues。事实证明,我的SQL Developer工具锁定了表并阻止了hibernate访问它。所以就像我在上次使用那个时候的查询访问表时所获得的数据一样快速获取快照。并没有应用我期望更新的查询执行的逻辑。而这些数据似乎在我清除任何缓存的任何尝试中都存在。

Yuuup ..我不得不砸我的额头.. 至少我更有信心我没有完全失去它..