Hibernate集合映射:一个真正好的关注分离?

时间:2012-10-20 17:13:41

标签: hibernate design-patterns dao separation-of-concerns

我是Hibernate ORM的新手,我想你可以帮助我更好地理解它。更准确地说,我发现自己在想是否能够很好地实现关注点的分离(当然是,我是我无法理解的......但请解释一下)。让我解释一下:在我看来,hibernate的主要目标是允许开发人员处理忘记数据库特性的类。好! 但让我们来看看这个案例:

我有一个对象,假设一个UserDetail与一个Athority对象有一个可能的关系。

@Entity(name="user")
@Table(name="USERS")
public class User implements UserDetails, DomainObject {

private static final long serialVersionUID = 1L;
private long id;
private String username;
private String password;
Collection<Authority> authorities = new ArrayList<Authority>();

public User() {
    super();
}


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id", unique=true, nullable=false)
public long getId() {
    return id;
}

//various getters & setters

@OneToMany(mappedBy="user")
public Collection<Authority> getAuthorities() {
    return authorities;
}

public void setAuthorities(Collection<Authority> authorities) {
    this.authorities = authorities;
}       
}

这是权威对象

@Entity(name="authority")
@Table(name="AUTHORITIES")
public class Authority implements GrantedAuthority, DomainObject{

private long id;
private User user;
private String authority;  //Spring Security demands them to start with "ROLE_"

public Authority() {
    super();
}


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id", unique=true, nullable=false)
public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

@ManyToOne
public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

@Column(name="authority", nullable=false)
public String getAuthority() {
    return this.authority;
}

public void setAuthority(String authority) {
    this.authority = authority;
}

}

好吧,假设我有一个UserDaoImpl和AuthorityDaoImpl(为简洁起见,这里省略)。如果我想创建一个新的UserDetails并坚持下去,我必须执行以下操作(它是一个inizializer bean,但这里并不重要):

@Component
public class Initializer {

    @Autowired
    @Qualifier("userDaoImpl")
    private UserDao userDao;
    @Autowired
    @Qualifier("authorityDaoImpl")
    private AuthorityDao authorityDao;

    @PostConstruct
    public void init()
    {
        if(userDao.loadUserByUsername("admin")==null)
        {
            System.out.println("starting initialization.");
            User admin = new User();
            admin.setUsername("admin");
            admin.setPassword("admin");

            Authority authority = new Authority();
            authority.setAuthority("ROLE_ADMIN");
            authority.setUser(admin);

            admin.getAuthorities().add(authority);

            userDao.save(admin);
            authorityDao.save(authority);
            System.out.println("admin user created.");
        }

    }
}
好吧,我觉得很奇怪我必须明确调用AuthorityDao来持久保存Authority对象。如果关注点的分离得到了很好的实现,我只需要将authority对象添加到admin autority列表中并单独保留管理员。如果我这样做,唯一要保留的实体是管理员。 你不觉得一样吗?我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

是。你错过了一件事。只需在cascade = CascadeType.ALL实体映射中的cascade = CascadeType.PERSIST映射中添加oneToManyAdmin(选择合适),如下所示。完成后,保存adimn也会保存authority

     @OneToMany(mappedBy="user", cascade = CascadeType.ALL)
     public Collection<Authority> getAuthorities() {
            return authorities;
     }

请在此处查找有关cascade类型和设置的详细信息:Hibernate Cascade

这是支持子实体的不同行为所必需的。例如,您的权限是一个主表,即从国家,货币等表格映射。在这里,您不希望持久/删除货币,国家和父对象。作为通用框架,它必须支持需求的几个方面。

答案 1 :(得分:1)

实际上,可以通过两种不同的方式在映射中启用关联对象的自动持久性:

要表达UML调用的组合(即依赖对象不能独立于引用对象而存在,不被其他对象引用),您可以使其成为@Embeddable。然后,Hibernate将插入,更新和删除依赖对象以及与其拥有对象(关联)。

要表达UML调用聚合的内容(即引用的对象具有自己的身份和独立的生命周期),您可以将引用的对象设为@Entity。您可以通过指定其级联属性来指示JPA自动级联持久性操作。

当然,持久化上下文加载的任何对象都会检测到更改,并在事务提交时自动将它们写入数据库。