我合并了一个新实例(它已保存到数据库中)然后我关闭了entitymanger,打开了一个新的实例,试图找到该实体但返回null。
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
查找功能:
public <T> T merge(Object source, Event<EntitiesPersistenceEventObject<T>> event, T t, boolean notifyGenericListeners) throws PersistenceException {
EntityManager entityManager = createEntityManager();
Object id = null;
PersistenceEventType eventType;
if (id == null || (id instanceof Number && ((Number) id).equals(0))) {
eventType = PersistenceEventType.ADDED_ENTITIES;
} else {
eventType = PersistenceEventType.UPDATED_ENTITIES;
}
try {
beginTransaction(entityManager);
t = entityManager.merge(t);
id = factory.getPersistenceUnitUtil().getIdentifier(t);
commitTransaction(entityManager);
//entityManager.refresh(t);
notifyListeners(event, source, eventType, notifyGenericListeners, t);
} catch (Exception ex) {
if (entityManager != null && entityManager.isOpen()) {
// entityManager.close();
}
throw new PersistenceException(ex);
} finally {
entityManager.close();
}
closeEntityManager();
return (T) find(t.getClass(), id);
}
getEntityManger直接调用此函数:
public <T> T find(Class<T> type, Object id) {
EntityManager entityManager = getEntityManager();
try {
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
//query.setHint("javax.persistence.cache.retrieveMode", "BYPASS");
T t = entityManager.find(type, id);
//entityManager.refresh(t);
return t;
} catch (Exception e) {
e.printStackTrace();
System.out.println("find exception type: " + type + " id=" + id);
throw e;
} finally {
// entityManager.close();
}
}
closeEntityManger只关闭threadEntityManger。
当对合并功能进行调试时,会生成一个新的id并将其保存在数据库中,但是当在合并函数的最后一行调用“find”时它返回null,它将在一个新的实体管理器上,因为我关闭了合并中的旧线程Entitymanger。 当debuging AbstractEntityMnagerImpl i
时public synchronized static EntityManager getThreadEntityManager() {
//entityMangersPoolCounter = entityMangersPoolCounter % ENTITY_MANGERS_POOL_MAX_COUNT;
EntityManager em = threadLocal.get();
if (em == null || !em.isOpen()) {
factory.getCache().evictAll();
em = factory.createEntityManager();
System.out.println("Hooooooory, creating new EnTITY manager!..." + em.hashCode());
em.
setProperty("javax.persistence.sharedCache.mode", SharedCacheMode.NONE);
em.
setProperty("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);
em.
setProperty("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
em.
setProperty("javax.persistence.FlushModeType", FlushModeType.AUTO);
threadLocal.set(em);
}
return em;
}
返回缓存模式REFRESH。
Hibernate entityManger版本4.2.6.Final Hibernate核心4.2.5.Final
另外,我在hibernate中启用了showsql选项,并在显示find时显示了select语句,但仍返回null。
我做错了什么,还是hibernate中的错误?
编辑:当我在服务器上执行生成的sql查询时,进一步调试hibernate生成好的sql,它返回一行代表实体,但仍然在hibernate中返回空集!!是否有来自java的连接的mysql缓存?EDIT2:跟踪日志http://pastebin.com/BaKzvuW3(在phpmyadmin中放置查询时相同(例如)我得到一行结果。
EDIT3:现在很清楚,mysql返回的结果是旧数据。即使我正在关闭实体管理器,提交更新/插入事务,即使我在读取之前尝试关闭事务(在提交旧事务后启动新事务)。
答案 0 :(得分:1)
看来这是mysql隔离和一致性的问题,似乎在调用
entityManager.getTransaction().commit();
不一定向mysql发送提交语句,或者它确实是mysql错误。
将连接隔离配置为低于“REPEATABLE READ”的级别,解决了以下问题:
cfg.setProperty("hibernate.connection.isolation", String.valueOf(Connection.TRANSACTION_READ_COMMITTED));