JPA:Eclipselink不会在数据库中保持双向关系

时间:2010-10-22 09:03:51

标签: java jpa eclipselink

我的Java EE 6应用程序中的域模型包含双向关系,如下所示:

@Entity
public  class Users implements PrimaryKeyHolder<String>, Serializable {
  @Id
  private String username;

  @ManyToMany(mappedBy= "users")
  private List<Category> categories;

  public List<Category> getCategories() {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }
    return Collections.unmodifiableList(categories);
  }

  public void addCategory(Category category) {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }

    categories.add(category);
    if (!category.getUsers().contains(this)) {
        category.addUser(this);
    }
  }

  public void removeCategory(Category category) {
    if (categories == null) {
        categories = new ArrayList<Category>();
    }

    categories.remove(category);
    if (category.getUsers().contains(this)) {
        category.removeUser(this);
    }
  }

  public void setCategories(Collection<Category> categories) {
    if (this.categories == null) {
        this.categories = new ArrayList<Category>();
    }

    for (Iterator<Category> it = this.categories.iterator(); it.hasNext();) {
        Category category = it.next();
        it.remove();
        if (category.getUsers().contains(this)) {
            category.removeUser(this);
        }
    }

    for (Category category : categories) {
        addCategory(category);
    }
  }
}

@Entity
public class Category implements PrimaryKeyHolder<Long>, Serializable {
  @Id
  private Long id;

  @ManyToMany
  private List<User> users;

  public List<User> getUsers() {
    if (users == null) {
        users = new ArrayList<User>();
    }
    return Collections.unmodifiableList(users);
  }

  protected void addUser(User user) {
    if (users == null) {
        users = new ArrayList<User>();
    }
    users.add(user);
  }

  protected void removeUser(User user) {
    if (users == null) {
        users = new ArrayList<User>();
    }
    users.remove(user);
  }
}

更新:我添加了关系管理代码。关系仅在用户端设置,因此,添加/删除方法在Categoriy类中受到保护。我通过setCategories为用户设置了类别。

Eclipselink正确生成了一个连接表CATEGORY_USERS。但是,它不会在其中保留任何信息(它只会缓存信息)。例如。当我在实体管理器(例如用户)上执行查找操作时,它返回完整的对象图(包括类别关系)。但是当我查看表格时,信息不会更新(即使事务已提交)。我还在我的代码中插入了一个flush操作,但没有成功。正确保存和更新基本信息(如String,Integer等列)。将日志级别转换为FINE后,我可以看到没有为关系和连接表执行任何SQL语句。但我确实看到了单向关系的SQL语句。

我的数据模型涵盖了广泛的单元测试,所有单元测试都成功通过。我基本上执行与容器相同的操作,提交事务,从db重新加载实体并检查关系是否正确设置,它们是什么(我正在使用内存中的derby数据库进行测试)。 p>

我的应用服务器是Glassfish v3.1-b17。

感谢任何帮助。 谢谢, Theo

3 个答案:

答案 0 :(得分:3)

确保您正在设置关系的两个方面。规范要求应用程序设置关系的两个方面,因为JPA中没有关系维护。

答案 1 :(得分:1)

经过无数次的尝试后,我终于得到了一个解决方案:我只是改变了关系的拥有方,即我将mappedBy属性放到类别实体中,如下所示:

@ManyToMany(mappedBy= "categories")
private List<User> users;

可以找到here

的解释

答案 2 :(得分:0)

四点:

1.-当您遇到错误时,更简单的找到解决方案在一个再现错误的示例(或单元测试)中隔离它们。在您的情况下,您可以使用更简单的getter和setter做一个示例(例如,删除unmodifiableList用法以及其他用于测试实际问题的必要方法)。

2.-我建议你使用 pojos for model ,没有任何逻辑。所以,从pojos中删除逻辑。

3.-我们正在使用eclipselink,我们没有持久关系的问题。因此,错误更有可能出现在您的代码中。

4.-使用“cascade = javax.persistence.CascadeType.ALL

测试注释关系

为我可怜的英语道歉:(