Hibernate - OneToMany - 多列

Posted

技术标签:

【中文标题】Hibernate - OneToMany - 多列【英文标题】:Hibernate - OneToMany - Several Columns 【发布时间】:2010-09-21 11:04:39 【问题描述】:

我有这两张表教师和联系人,一个教师可以有 x 个联系人。所以在这里我们正在查看@OneToMany 关联。

表结构:

用户 [用户 ID、用户名、电子邮件、...] 联系人 [contactid, contactname, ref, reftype,...]

我想从我的用户类中加载所有用户的联系人。为此,我会进行类似

的查询
Select * from contact as c WHERE c.ref=8240 AND c.reftype='T';

8240 是一个随机用户 ID,引用类型 T 是教师。由于此联系人表也用于学校联系人和/或我们可能拥有的任何其他类型的客户。 问题是我不知道如何使用 Hibernate 来做到这一点。我应该使用 embedbedId 吗?还是 JoinColumns?

到目前为止,我所做的是将我的老师与contact.ref=teacher.teacherid 的联系人联系起来,但我想要的是:

contact.ref=teacher.teacherid AND contact.reftype='T'

我该怎么做?

这是我的代码 老师.class

private Integer teacherid;
private Set<Contact> contact;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "teacherid", unique = true, nullable = false)
public Integer getTeacherId() 
    return teacherid;


 @OneToMany(fetch = FetchType.EAGER)
 @JoinColumns(
     @JoinColumn(name="ref"),
 )
public Set<Contact> getContact() 
    return contact;


public void setContact(Set<Contact> contact) 
    this.contact = contact;

联系人.class

@Entity
@Table(name = "contact")
public class Contact implements java.io.Serializable 

    private Integer contactid;
    private String contactname;
    private String contacttype;
    private String reftype;
    private int ref; 

    /*private Teacher teacher;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumns(
        @JoinColumn(name = "ref"),
        @JoinColumn(name = "reftype")
    )
    public Teacher getTeacher() 
        return teacher;
    
    public void setTeacher (Teacher teacher) 
        this.teacher= teacher;
    
*/
    private Set<ContactItem> contactItems;
    private Set<ContactAddress> contactAddressess;

    @OneToMany(fetch=FetchType.EAGER)
    @JoinColumn(name="contactid")
    public Set<ContactItem> getContactItems()
        return contactItems;
    

    public void setContactItems(Set<ContactItem> contactItems) 
        this.contactItems = contactItems;
    

    @OneToMany(fetch=FetchType.EAGER)
    @JoinColumn(name="contactid")
    public Set<ContactAddress> getContactAddressess()
        return contactAddressess;
    

    public void setContactAddressess(Set<ContactAddress> contactAddressess) 
        this.contactAddressess = contactAddressess;
    

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "contactid", unique = true, nullable = false)
    public Integer getContactid() 
        return this.contactid;
    

    public void setContactid(Integer contactid) 
        this.contactid = contactid;
    

    @Column(name = "contactname", nullable = false)
    public String getContactname() 
        return this.contactname;
    

    public void setContactname(String contactname) 
        this.contactname = contactname;
    

    @Column(name = "contacttype", nullable = false)
    public String getContacttype() 
        return this.contacttype;
    

    public void setContacttype(String contacttype) 
        this.contacttype = contacttype;
    

    @Column(name = "reftype", nullable = false, length = 1)
    public String getReftype() 
        return this.reftype;
    

    public void setReftype(String reftype) 
        this.reftype = reftype;
    

    @Column(name = "ref", nullable = false)
    public int getRef() 
        return this.ref;
    

    public void setRef(int ref) 
        this.ref = ref;
    

    public String toString()
        return "\n#"+this.contactname+" : ("+this.ref+"-"+this.reftype+") \n" 
                    +"#Items-----\n"+getContactItems()+"\n" 
                    +"#Address---\n"+getContactAddressess()+"\n";
    

【问题讨论】:

teacheruser(如果不是,为什么要显示用户表)?你有某种继承吗? ref 列是否有外键约束? 即使您进行了编辑,我认为我在下面的回答总体上仍然是正确的。您必须更改详细信息以匹配您的情况。 个人认为设计有问题。请澄清用户/教师和联系人之间的关系,这很重要。 对不起他的困惑.. 让我们称我的 User.class Teacher.class,我在 db 中的表是教师。关于TEacher和Contact之间的关系我想我很清楚-> contact.ref=teacher.teacherid AND contact.reftype='T' 在我的联系表中我没有任何FK,我只是使用索引'ref' ,'reftype' 显然是 PK contactid 【参考方案1】:

假设TeacherUser,并且每个用户都有contacts

用户类

@OneToMany(mappedBy = "user", targetEntity = Contact.class, orphanRemoval=true)
@Cascade(CascadeType.ALL)
private Set<Contact> contacts = new ConcurrentSkipListSet<Contact>();

//No setContacts here. 

联系人.class

@ManyToOne
private User user;

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

就是这样。

【讨论】:

我认为您的解决方案行不通。因为我看不到您如何管理我在 User(Teacher) 类和 Contact 类之间的特殊关系。关系是 teacher.teacherid=contact.ref AND contact.reftype='T'。【参考方案2】:

首先,因为有一个用户表而没有教师表(教师似乎是用户行的子集,由“类型”列表示)我不会有一个用户表和教师模型。我将只有一个用户模型。如果您以 Hibernate 方式进行操作,那么 Hibernate 会要容易得多,这是每个表一个模型,模型具有相同的名称。例如,如果您这样做,您可以使用工具自动生成(逆向工程)所有模型类。这意味着 Hibernate 工具将查看您的表、外键等,并为您的表生成 适当的 Java 代码。开始更改表格时非常方便。

通常您会对模型类进行逆向工程。由于这些是机器生成的,您不想更改它们,因为更改将在下次对模型进行逆向工程时被覆盖。对于像你这样的情况,我所做的是创建一个名为 DAO - 数据访问对象或 DAO 的类。

public class UserDAO 
    public static User getTeacher(EntityManager em, Long id) 
        try 
        IForgotTheType query = em.createQuery("User from User user, Contact contact where contact.ref=user.teacherid AND contact.reftype='T' and User.id=:id");
        query.setParameter("id", id);
        return (User) query.getSingleResult();
         catch (NoResultException e) 
           return null;
         catch (Exception e) 
           throw new RuntimeException(e);
        
 

显然,我不确定您的表结构和列名,但您明白了。您可以看到我在上面的查询中插入代码的位置。现在您只需调用 UserDAO.getTeacher() 即可获得教师。使用 DAO - 否则您的代码中无处不在 会有 Hibernate 代码,从而使维护更加困难。

Check out section 3.4 of this.

【讨论】:

感谢那个托尼,但我现在有一些额外的问题。如何从我的用户(教师)对象访问我的联系人对象?我的用户类是什么样子的?应该是怎样的映射? 要访问联系人对象,您会看到 Hibernate 闪耀:userInstance.getContact(); 返回从数据库中获取的联系人实例。 用户的映射应该是什么?这就是我所做的。 (这是免责声明!) 1. 正确定义您的数据库模式。这意味着您将拥有一个 User 表,其中包含正常的内容,包括数据库使用序列分配的主键。应该有一个contact_id 列。然后创建一个包含联系人内容的联系人表。使用 user.contact_id 列定义外键。然后我对模型进行逆向工程。我已经使用 Hibernate 完成了两个大型项目。我从来没有手动编码过模型。逆向工程是胜利。 这在您必须更改数据库表时变得很明显。这破坏模型。不用担心,只需对它们进行重新逆向工程。在我工作的地方,我们有一条规则——永远不要手动更改模型——因为这让我们可以根据需要进行逆向工程,而不必担心。我们确实编写了一个非常糟糕的预处理器,它在每个模型中塞进了一些东西,比如何时使用级联删除等。

以上是关于Hibernate - OneToMany - 多列的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate - OneToMany 注释导致选择查询的左连接不匹配

Hibernate OneToMany SELECT 在实体的映射中给出重复的列

休眠 OneToMany 和 ManyToOne?

hibernate 映射总结

Hibernate - OneToMany - 多列

Hibernate 从 onetomany 中删除