gpt4 book ai didi

java - 如何使用 JPA/Hibernate 在 Repository 中实现保存

转载 作者:行者123 更新时间:2023-11-30 10:59:48 25 4
gpt4 key购买 nike

我想要的是在 JPA/Hibernate 应用程序中实现存储库模式。我有一个描述我的存储库基本契约的通用接口(interface):

public interface EntityRepository<Entity extends Object, EntityId> {
Entity add(Entity entity);

Entity byId(EntityId id);

void remove(Entity entity);

void removeById(EntityId id);

void save();

List<Entity> toList();
}

下面是这样一个接口(interface)的实现:

public class EntityRepositoryHibernate<Entity extends Object, EntityId>
implements Serializable,
EntityRepository<Entity, EntityId> {
private static final long serialVersionUID = 1L;

@Inject
protected EntityManager entityManager;
protected Class<Entity> entityClass;

public EntityRepositoryHibernate(Class<Entity> entityClass) {
this.entityClass = entityClass;
}

public EntityManager getEntityManager() {
return entityManager;
}

@Override
public Entity add(Entity entity) {
entityManager.persist(entity);
return entity;
}

@SuppressWarnings("unchecked")
@Override
public Entity byId(EntityId id) {
DetachedCriteria criteria = criteriaDAO.createDetachedCriteria(entityClass);
criteria.add(Restrictions.eq("id", id));
return (Entity)criteriaDAO.executeCriteriaUniqueResult(criteria);
}

@Override
public void remove(Entity entity) {
if(entity==null)
return;
entityManager.remove(entity);
}

@Override
public void removeById(EntityId id) {
remove(byId(id));
}

@Override
public List<Entity> toList() {
throw new UnsupportedOperationException("toList() not implemented in "+entityClass.getName());
}

@Override
public void save() {
entityManager.flush();
}
}

除了 save() 之外,所有方法都工作正常,所以这是这里的重点。

据我所知,Hibernate 能够跟踪查询(byId() 方法)返回的任何实例中的所有更改。因此,save() 方法的想法是保存任何检索和更改的实例,这就是该方法不接收任何参数的原因,它应该保存必须保存的所有内容(这意味着,任何在存储库存在时被检索并以某种方式更新的持久实例。

在可能的情况下,我可以调用 byId() 10 次以检索 10 个不同的实例并仅更改其中的 4 个。这个想法是,通过调用一次 save(),这 4 个实例将保存在数据服务器中。

问题是当我调用 flush() 时,我收到一个异常,指出没有 Activity 事务。由于我使用的是 JTA 持久性单元,因此通过调用 entityManager.getTransaction() 以编程方式打开事务是非法的。

考虑到这一点,如何修复代码?

最佳答案

首先,您似乎误解了 EntityManager.flush 方法的用途。它不提交由持久性上下文管理的任何更改,只是将 SQL 指令发送到数据库。我的意思是,对于同一个 JTA 事务,当您检索和修改某些实体实例时,更改/SQL 指令被缓存起来等待发送到数据库。如果提交了底层事务,则此更改将与提交指令一起刷新到数据库。如果您在提交事务之前调用 flush,则仅在调用点之前刷新更改(好吧,一些 SQL 指令可能由于这件事的原因而先前已被刷新),但不会发送提交指令。

如何修复?

我建议你不要混Repository Pattern与交易操纵。

看起来您正在使用容器管理事务 (javaee tutorial),所以只需删除 save 方法并让容器管理事务。这将改变您的关注点,您现在必须关心回滚事务 (throwing exception or invoking setRollbackOnly),但您不需要显式提交。

关于java - 如何使用 JPA/Hibernate 在 Repository 中实现保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31791397/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com