hibernate多对一映射,我应该这样插入吗?

时间:2012-11-02 16:11:48

标签: java hibernate orm

假设我们有两个表,userdomain。用户可以拥有一个域,一个域可以用于许多用户。所以我们会做多对一的单向:

@Entity
@Table(name = "DOMAIN")
public class Domain implements Serializable
{
    @Id
    @Column(name = "DOMAIN_ID")
    private Integer domainId;

    @Column(name = "NAME")
    private String domainName;
}

@Entity
@Table(name = "\"USER\"")
public class User implements Serializable
{
    @Id
    @GeneratedValue(generator = "USER_SEQ")
    @GenericGenerator(name = "USER_SEQ", strategy = "sequence", parameters = @Parameter(name = "sequence", value = "SEQ_USER_ID"))
    @Column(name = "USER_ID", nullable = false)
    private Long userId;

    @Column(name = "FIRST_NAME")
    private String firstName;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "DOMAIN_ID")
    @ForeignKey(name = "DOMAIN_ID")
    private Domain domain;
}

Domain表是不可变的,字典。虽然User是可编辑的表格。

我正在创建一个基本表单,用户选择将在其中创建新用户的域。让我们说我的控制器收到了这些数据:

Integer domainId = 1;
String firstName = "aaa";

所以我正在创建新用户:

User newUser = new User();
newUser.setFirstName( firstName );

现在我的问题是,我应该这样做吗?

Domain domain = somthingThatWillFetchObjectFromDb.getDomain( domainId );
newUser.setDomain( domain );
//save user

这将生成额外的选择,以获取域。当然我可以使用Integer domainId而不是POJO,但这不是ORM。再问一遍,问题应该是这样吗?

2 个答案:

答案 0 :(得分:3)

是的,那就是你应该做的。如果您不想从数据库中实际加载域信息,请使用奇怪命名的Session.load()方法而不是Session.get()方法。如果域尚未加载到会话中,Session.load()将只返回域的单元化实体代理(就像您已经加载了一些与域的延迟关联的实体一样),而不会访问数据库。

也就是说,如果域名不可更改,为什么要在域名字段中设置@Cascade(CascadeType.ALL)?这意味着每次合并或更新用户时,域名也将被合并或更新。更糟糕的是:如果删除用户,域名也将被删除(如果其他用户引用同一个域,这当然会导致异常)。

答案 1 :(得分:1)

是。要保存像User这样的子实体,您需要在其中设置父实体,即Domain实体。

另一种方法是在父实体中定义双向映射(OneToMany),即。域,加载Domain,在User中添加一个或多个Domain对象并仅保存Domain个实体,例如

Domain实体:

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "domain")
  List<User> users = null;

  public List<User> getUsers(){
     return this.users;
  }

  public void setUsers(List<User> user){
     this.users = users;
  }

  public void addUser(User user){
     user.setDomain(this);//set the parent entity
     if(this.users==null){
        this.users = new ArrayList<User>();
     }
     this.user.add(user);
  }

然后保存用户:

   User user1 = new User();
   ......
   User user2 = new User();
   ......
   Domain domain = loadDomain();//<- use actual method to load the domain
   //< add all the users to be saved at once
   domain.addUser(user1); 
   domain.addUser(user2);
   //save parent entity i.e. domain
   saveDomain(domain);//use actual method to save the entity