我使用JPA + Hibernate + Spring来完成简单的工作。 我写了下一个模块:
服务:
@Autowired
private VolMng volMng;
@Service
public class Dist {
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public void gen() {
MeterLog mLog = em.find(MeterLog.class, 3625190);
Lst volTp = lstMng.findByCD("Fact Vol");
Vol vol = new Vol((MeterLog) mLog, volTp, 7777.77d);
volMng.add(vol);
//point-1:
for (Vol a : mLog.getVol()) {
System.out.println("found="+a.getId()+" vol="+a.getVol1());
}
...
...
服务:
@Service
public class VolMngImpl implements VolMng {
@Autowired
private VolDAO vDao;
public void add(Vol vol) {
vDao.add(vol);
}
}
DAO:
@Repository
public class VolDAOImpl implements VolDAO {
@PersistenceContext
private EntityManager em;
public void add(Vol vol) {
em.persist(vol);
}
}
我正在尝试将一些记录添加到子实体Vol。
但是在第1点的volMng.add(vol)之后,我没有看到任何添加的记录(子实体)。 为什么?
UPD
当然我在交易结束后会看到这些记录,但为什么我不能在之前做到?它们必须在内存缓存中......
upd2
我的spring.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd">
<!-- *******************************
***** CACHE CONFIGURATION *****
******************************* -->
<cache:annotation-driven cache-manager="cacheManager" />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
<property name="shared" value="true"/>
</bean>
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="URL" value="jdbc:oracle:thin:@192.168.1.1:1521:DEV" />
<property name="user" value="ora"/>
<property name="password" value="ora"/>
<property name="connectionCachingEnabled" value="true"/>
</bean>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
</bean>
<context:component-scan base-package="com.ric.bill" />
<context:component-scan base-package="com.ric.bill.dao.impl" />
<context:component-scan base-package="com.ric.bill.mm.impl" />
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="proxy" transaction-manager="transactionManager"/>
<context:spring-configured />
<context:annotation-config />
</beans>
答案 0 :(得分:1)
收藏不会在会话中自动更新。 一旦您重新加载所有内容,它就会出现,但您必须手动将其添加到拥有对象的子集合中,以防您在当前会话中需要它。
答案 1 :(得分:0)
要解决这个问题,我必须将子实体添加到父级,如下所示:
MeterLog mLog = em.find(MeterLog.class, 3625190);
Lst volTp = lstMng.findByCD("Fact Vol");
Vol vol = new Vol((MeterLog) mLog, volTp, 7777.77d);
mLog.getVol().add(vol);
//point-1:
for (Vol a : mLog.getVol()) {
System.out.println("found="+a.getId()+" vol="+a.getVol1());
}
答案 2 :(得分:0)
要回答实际问题 - 为什么你看不到新添加的实体......
运行select语句并将结果放在java对象中:
MeterLog mLog = em.find(MeterLog.class, 3625190);
find最终创建select语句,并根据您用来定义映射的jpa注释,通过hibernate将结果集转换为MeterLog对象。从这一点开始,您的代码不会更改此对象。您可以使用以下代码创建新实体:
volMng.add(vol);
直接将新实体持久保存在数据库中。但是,这是在select已经返回您要求的数据之后。您没有做任何事情来更改或刷新您已经获得的结果集。底层数据存储区(oracle,mysql,无论如何)都不记得你已查询过它并且正在保存其数据的副本,因此它无法提醒您基础数据已更改的事实
正如您在答案中提到的,您可以将新实体直接添加到对象的集合中:
mLog.getVol().add(vol);
在某些情况下,这将在事务成功完成时将新实体持久保存到数据库中,但也允许您在循环访问集合时查看实体,从而观察您的实体。然而,你已经违反了德米特的法则 - 在创建时,将自己添加到给定MeterLog的卷集合中应该是Vol的责任。