java Spring-Hibernate 持久化不会导致插入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5168950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring-Hibernate persist does not result in insert
提问by AlexV
I'm trying to implement a simple DAO. I have a Dao:
我正在尝试实现一个简单的 DAO。我有道:
@Repository("iUserDao")
@Transactional(readOnly = true)
public class UserDao implements IUserDao {
private EntityManager entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public User getById(int id) {
return entityManager.find(User.class, id);
}
@Override
public boolean save(User user) {
entityManager.persist(user);
entityManager.flush();
return true;
}
@Override
public boolean update(User user) {
entityManager.merge(user);
entityManager.flush();
return true;
}
@Override
public boolean delete(User user) {
user = entityManager.getReference(User.class, user.getId());
if (user == null)
return false;
entityManager.remove(user);
entityManager.flush();
return true;
}
And an entity:
和一个实体:
@Entity
@Table(name = "users")
public class User {
private int id;
private Date creationDate;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public User() {
}
public User(Date creationDate) {
this.creationDate = creationDate;
}
public void setId(int id) {
this.id = id;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
Here's appContext.xml: `
这是 appContext.xml:`
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"
p:persistenceUnitName="test">
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="MYSQL" p:showSql="true"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<tx:annotation-driven/>`
Unless I call flush()
after persist()
or merge()
the insert in not executed.
Why is that?
If I remove @Transactional
then I get error on "no transaction is in progress" on flush, but if remove flush nothing inserted to the DB.
除非我flush()
在之后调用persist()
或merge()
插入未执行。这是为什么?如果我删除@Transactional
然后我在刷新时收到“没有正在进行的事务”错误,但是如果删除刷新没有插入到数据库中。
回答by axtavt
It works this way because you marked transaction as read only with @Transactional(readOnly = true)
.
它以这种方式工作,因为您将事务标记为只读@Transactional(readOnly = true)
。
As you can see, it doesn't make your transactions actually read-only since you still can persist changes by calling flush()
manually. However, it disables automatic flush at the end of transaction, so that changes are not persisted without manual flush.
如您所见,它不会使您的事务实际上是只读的,因为您仍然可以通过flush()
手动调用来保持更改。但是,它会在事务结束时禁用自动刷新,因此如果没有手动刷新,更改就不会持久化。
You need either remove readOnly
from class-level annotation, or override it on non-read-only methods with method-level annotations:
您需要readOnly
从类级注释中删除,或者使用方法级注释在非只读方法上覆盖它:
@Override
@Transactional(readOnly = false)
public boolean save(User user) { ... }
Also note that transaction demarcation is usually applied to service layer methods, not to DAO methods. In particular, when writing DAO methods you actually don't know which transactions should be read-only, and which are not. This information is available only when designing service layer, as you can see in this example:
另请注意,事务划分通常应用于服务层方法,而不是 DAO 方法。特别是,在编写 DAO 方法时,您实际上不知道哪些事务应该是只读的,哪些不是。此信息仅在设计服务层时可用,如您在此示例中所见:
public class UserService {
@Autowired UserDAO dao;
@Transactional(readOnly = true)
public User getUserById(int id) {
return dao.getById(id); // getById() can participate in effectively read-only transaction
}
@Transactional
public void changeUserName(int id, String newName) {
User u = dao.getById(id); // Or not
u.setName(newName); // Change will be flushed at the end of transaction
}
}
回答by limc
Try setting the transactional propagation to required, and remove all flush()
:-
尝试将事务传播设置为必需,并删除所有flush()
:-
@Repository("iUserDao")
@Transactional(propagation=Propagation.REQUIRED)
public class UserDao implements IUserDao {
...
}