**问题更新
因此,似乎以下所述的问题与查询或使用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进行检索,则一切正常,并且我得到了期望的查询结果。
显然,我不想为此使用重复的类,但是这使我相信,时髦的结果是由于在测试的整个生命周期中,我在持久性上下文中持续管理的对象所致。不管我使用persist()还是merge(),我都得到相同的结果。
谁能建议我如何正确处理这种情况?看来我需要避免托管对象来查看所需的实际查询结果。也许需要在检索结果之前先提交数据?如何修改上面的JUnit init()和cleanUp(),以允许我插入一些虚拟数据,运行不受事务中托管对象影响的测试,然后清除/回滚虚拟数据?
问题
我有一个正在SQL Developer Lite中测试的查询,该查询可用于创建休眠的本机查询。我遇到的问题是当我在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)中
基本上这是正在发生的事情,还有一些其他东西可用于填充参数,但对于任何参数,只要将这些参数硬编码在我作为测试对象运行的查询字符串中,它就不会对直接查询产生任何影响。
Query query = em.createNativeQuery(BASIC_QUERY_STRING.toString(), MY_JOIN_MAPPING);
结果很奇怪
现在注意serviceid列,就好像我只是没有使用LAST_VALUE和PARTITION一样。
我使用last_value和partition的目标是获取一个不带0的serviceid结果集。不幸的是,我没有足够的空间来显示更多的表数据,但是我要对其进行排序的是lastupdated列,这是一个基本的时间戳,其目的是“填充”来自表中各行的数据此表,然后选择第一行,并将每一行的所有数据汇总为一个结果。我需要我的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中运行。那么,为什么似乎无法休眠似乎无法处理LAST_VALUE / PARTITION BY?我没有看到任何错误,只是没有看到基于在SQL Developer中运行相同查询而希望看到的结果。
边注
只是为了查看休眠是否简单地忽略了last_value /分区,我故意弄乱了last_value和partition以查看它是否完全看到了...
示例:代替这个
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”,以查看它是否甚至在使用它,就像冬眠或介于两者之间的某物不在乎使用它。
附加说明
这是我来自persistance.xml的两个道具。我在连接或运行任何查询时都没有问题,只是不明白为什么我没有从休眠中看到与在SQL Developer中相同的结果。
<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"/>
最佳答案
事实证明,该问题与运行本机查询以及使用LAST_VALUE和PARTITION BY函数无关。原来是数据,而且似乎是休眠中缓存的数据。这演变成一个新的问题,在这里Hibernate with JPA 1.0 Caching Issues看到。事实证明,这是我的SQL Developer工具锁定了表并阻止了休眠访问它。因此,就像我不断从该时间上一次使用查询访问表时所获得的数据的时间获取快照一样。并没有应用我期望更新后的查询执行的逻辑。而且,这些数据似乎可以在我清除缓存的任何尝试中幸免。
Yuuup ..我不得不打我的额头..
至少我更有信心我不会完全失去它。
关于java - SQL Developer Client和JPA/Hibernate结果之间的不同LAST_VALUE结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21892957/