【问题标题】:JPA entities, servicelayer and repositories: Am i doing this right?JPA 实体、服务层和存储库:我这样做对吗?
【发布时间】:2016-02-20 09:55:43
【问题描述】:

我不太确定,如果我在我的服务/持久层中做得对。 就我而言,我有四个实体:用户、类别、投资和投资重复:

用户:

public class User implements Identifiable, Serializable {

@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.LAZY, 
orphanRemoval = true)
private List<Investment> investmentList;

@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "user_investment", joinColumns = { @JoinColumn(name = "user") }, 
inverseJoinColumns = { @JoinColumn(name = "investment") })
private List<Investment> publicInvestmentList;

@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, 
fetch = FetchType.LAZY, orphanRemoval = true)
private List<Category> categoryList;

...
}

类别:

public class Category implements Identifiable, Serializable {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner", columnDefinition = "BIGINT(20)")
@NotNull
private User owner;

@OneToMany(mappedBy = "category", fetch = FetchType.LAZY)
private List<Investment> investmentList;

...
}

投资:

public class Investment implements Identifiable, Serializable {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner")
@NotNull
private User owner;

@ManyToMany(mappedBy = "publicInvestmentList")
private List<User> publicUserList;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category")
@NotNull
private Category category;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "investmentrepeat")
@NotNull
private InvestmentRepeat investmentRepeat;

@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
        CascadeType.REFRESH }, fetch = FetchType.LAZY)
@JoinColumn(name = "owninginvestmentrepeat", columnDefinition = "BIGINT(20)")
private InvestmentRepeat owningInvestmentRepeat;

...
}

投资重复:

public class InvestmentRepeat implements Identifiable, Serializable {
@OneToMany(mappedBy = "investmentRepeat", fetch = FetchType.LAZY)
private List<Investment> investmentList;

@OneToOne(mappedBy = "owningInvestmentRepeat", fetch = FetchType.LAZY)
@NotNull
private Investment parentInvestment;

...
}

对于每个实体,都存在一个无状态服务类,例如用户服务,类别服务。

我的第一个问题是,如果我为用户创建新类别的功能是正确的,我是否需要在持久化类别后更新用户实体?

分类服务:

 public Category createWithReferences(String categoryTitle, User owner,
        boolean deleteable) throws ServiceException,
        EntityPersistenceException {
    if (owner == null) {
        throw new ServiceException(getMessageService()
                .getMessageFromBundle("error.user_not_found_by_id"));
    }
    if (categoryTitle == null || categoryTitle.isEmpty()) {
        throw new ServiceException(getMessageService()
                .getMessageFromBundle("error.category.no_title"));
    }

    Category newCategory = new Category(categoryTitle, owner, deleteable);
    owner.addCategorie(newCategory);

    newCategory = this.repository.create(newCategory);
    userService.update(owner);

    return newCategory;
}

BaseEntityRepository 实现实体的 CRUD 操作:

@Override
public T create(T obj) throws EntityPersistenceException {
    EntityTransaction tx = getEntityManager().getTransaction();
    tx.begin();
    try {
        getEntityManager().persist(obj);
        tx.commit();
    } catch (PersistenceException e) {
        if (tx.isActive()) {
            tx.rollback();
        }
        throw new EntityPersistenceException(
                "Could not create Object of Instance: "
                        + obj.getClass().getCanonicalName()
                        + "; ErrorMessage: " + e.getMessage());
    }

    return obj;
}

@Override
public T update(T obj) throws EntityPersistenceException {
    EntityTransaction tx = getEntityManager().getTransaction();
    tx.begin();
    try {
        obj = this.getEntityManager().merge(obj);
        tx.commit();
    } catch (PersistenceException e) {
        if (tx.isActive()) {
            tx.rollback();
        }
        throw new EntityPersistenceException(
                "Could not update Object of Instance: "
                        + obj.getClass().getCanonicalName()
                        + "; ErrorMessage: " + e.getMessage() + "; ID: "
                        + obj.getId());
    }
    return obj;
}

@Override
public void delete(T obj) throws EntityPersistenceException {
    EntityTransaction tx = getEntityManager().getTransaction();
    tx.begin();
    try {
        if (obj != null) {
            long id = 0;
            if (obj instanceof Identifiable) {
                id = ((Identifiable) obj).getId();
                T entity = getEntityManager().find(getType(), id);
                //entity = getEntityManager().merge(entity);
                getEntityManager().remove(entity);
                tx.commit();
            }
        }
    } catch (PersistenceException e) {
        if (tx.isActive()) {
            tx.rollback();
        }
        throw new EntityPersistenceException(
                "Could not delete Object of Instance: "
                        + obj.getClass().getCanonicalName()
                        + "; ErrorMessage: " + e.getMessage() + "; ID: "
                        + obj.getId());
    }
}

当我创建实体后不更新用户时,当我通过em.find(...)刷新用户时,用户不包含新类别,但新类别是在数据库中创建的。

另一点是,当我使用 Investmentrepeat 持久化新投资时,在 db-tableinvestmentrepeat 中,parentinvestment 的 id 每次都是 0,或者当我删除 @NotNull 注释时,id 为 null。我如何在该类别中添加投资是否正确?这是我创建新投资的函数:

投资服务:

public Investment createWithReferences(User owner, String description,
        double amount, Date investDate, Category category,
        InvestmentRepeat investmentRepeat, boolean isParentInvestment)
        throws ServiceException, EntityPersistenceException {
    if (owner == null) {
        throw new ServiceException(getMessageService()
                .getMessageFromBundle("error.user_not_found_by_id"));
    }
    if (category == null) {
        throw new ServiceException(getMessageService()
                .getMessageFromBundle("error.category_is_null"));
    }
    if (investmentRepeat == null) {
        throw new ServiceException(getMessageService()
                .getMessageFromBundle("error.investmenterepeat_is_null"));
    }

    // Create investment
    Investment newInvestment = new Investment(investDate,
            new LocalDateTime(DateTimeZone.UTC), amount, description,
            owner, category, investmentRepeat);
    // add Investment to investmentRepeat and Category
    investmentRepeat.getInvestmentList().add(newInvestment);

    if (isParentInvestment) {
        investmentRepeat.setParentInvestment(newInvestment);
        newInvestment.setOwningInvestmentRepeat(investmentRepeat);
    }

    owner.findCategory(category).addInvestment(newInvestment);
    owner.addInvestment(newInvestment);

    // create investment
    newInvestment = this.create(newInvestment);

    // update Owner
    userService.update(owner);

    return newInvestment;
}

我希望有人能告诉我我犯了哪些错误以及我对 jpa 的了解在哪里是错误的 :)

谢谢!

【问题讨论】:

    标签: jpa ejb eclipselink


    【解决方案1】:

    向用户添加类别的最简单方法是执行以下操作。

    1. 确保您的用户拥有类别列表,否则它将仅用您最新的类别替换所有类别
    2. 将创建的新类别添加到列表中
    3. 更新用户实体,因为您对关系进行了级联,类别将保持不变,并且将与用户进行匹配。

    现在来看第二个问题。

    【讨论】:

    • 感谢您的回答!你的意思是我应该评论newCategory = this.create(newCategory)。但是当我这样做时,用户类别列表中新创建的类别具有 id = null。当我现在向列表中添加第二个新类别并更新用户时,有两个类别的 id = null 并且数据库类别表中的 ids 发生变化。
    • 你应该这样做:Category newCategory = new Category(categoryTitle, owner, deleteable); owner.addCategorie(newCategory); userService.update(owner);
    • 当我这样做时,例如owner.getCategorList().get(0).getId() 为空。因为会对类别进行合并操作。 newCategory 在数据库中,但在所有者列表中有一个空 id,直到我刷新所有者:/
    猜你喜欢
    • 1970-01-01
    • 2014-07-02
    • 2015-06-09
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2023-03-19
    相关资源
    最近更新 更多