views:

85

answers:

2

Hello there,

I have those 2 tables Teacher and Contact, a teacher can have x Contacts SO here we are looking at a @OneToMany association.

Tables Structure:

User [userid, username, email,...]

Contact [contactid, contactname, ref, reftype,...]

I want to load from my User Class all the User's contacts. To do that I would do a query like

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

8240 being a random userid and reftype T being for Teacher. As this contact table is used as well for school contacts and/or anyother type of customer we could have..

The problem is I have no idea how to do this with Hibernate. I checked a lot of websites but I still don't get it and I need HELP!! Should I use embedbedId? or a JoinColumns?

What I have done so far is to link my teacher to contacts having contact.ref=teacher.teacherid but what I want is :

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

How do I do that?

Here is my code Teacher.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;
}

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";

  }

}
A: 

Assuming that Teacher is a User, and that every user has contacts.

User.class

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

//No setContacts here. 

Contact.class

@ManyToOne
private User user;

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

That's it.

pakore
I don't think your solution would work. As I don't see how you manage my special relationship between the User(Teacher) class and the Contact Class. The relationship being teacher.teacherid=contact.ref AND contact.reftype='T'.
deluxouss
A: 

First, since there's a User table and no Teacher table (teachers seem to be a sub-set of user rows, denoted by a 'type' column) I wouldn't have a table of User and a Teacher model. I would have only a User model instead. Hibernate is much easier if you do things the Hibernate way, which is one model per table with the model having the same name. For example, if you do this, you can use a tool to auto-generate (reverse engineer) all your model classes. This means a Hibernate tool will look at your tables, foreign keys, etc and generate appropiate Java code for your tables. Very very convenient when you start making table changes.

Normally you'll reverse engineer the model classes. Since these are machine-generated you don't want to change them because the changes will be over-written the next time to reverse-engineer the models. What I do for conditions such as yours is to create a class called a DAO - Data Access Object, or 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);
        }
} 

Obviously I am not sure about your table structure and column names but you get the idea. You can see where I inserted your code into the query above. Now you can get a teacher by simply calling UserDAO.getTeacher(). Use DAOs - otherwise you'll have Hibernate code everywhere in your code making maintenance more difficult.

Check out section 3.4 of this.

Tony Ennis
Thanks for That Tony, But I have some extra questions now. How would I access my contact object from my User(Teacher) object? And how does my User class look like? What kind of mapping should it be?
deluxouss
To access the contact object, you'll see Hibernate shine: `userInstance.getContact();` returns an instance of Contact fetched from the database.
Tony Ennis
What should the mapping on user be? Here's what I do. (That's a disclaimer!) 1. Define your database schema properly. That means you'll have a User table with normal stuff in it including a primary key assigned by the database using a sequence. There should be a contact_id column. Then create a Contact table that has contacty stuff in it. Define a foreign key using the user.contact_id column. Then I reverse engineer the model. I've done two large projects using Hibernate. I have never hand-coded a model. Reverse engineering is the win.
Tony Ennis
this becomes evident when you have to change a database table. This *breaks* models. Not to worry, just re-reverse engineer them. We had a rule where I worked - never change a model by hand - because that allowed us to reverse-engineer as needed with no fear. We did write a totally crappy pre-processor that jammed some stuff into each model such when to use cascading deletes etc.
Tony Ennis