0

I am new in Hibernate. I am developing a backend service with Java and Hibernate.

I have a Student entity, it has a many-to-many relationship with Group entity. That's in database, I have a student table and a group table:

@Entity
@Table(name = "student")
public class Student {
   private int student_id; //primary key

   @ManyToMany(mappedBy = "students")
   private Set<Group> groups = new HashSet<Group>();

   @ManyToMany(cascade = {CascadeType.ALL})
   @JoinTable(name="student_group",
           joinColumns={@JoinColumn(name="student_id")},
           inverseJoinColumns={@JoinColumn(name="group_id")})
   public Set<Group> getGroups() {
       return groups;
   }

   public void setGroups(Set<Group> groups) {
      this.groups = groups;
   }

   //Setter & Getter for student_id
   ...

}

As you see in above hibernate annotation, there is a join table student_group in database. What I want to achieve is that, when a client's request is arriving to my backend service (with a student id), I would like to know whether the student_group join table in database has updated for this student, e.g. whether a new row (new group) is inserted (assigned to this student) or whether an existing row has been updated value. If there is such update/change, I will inform client.

With hibernate, how can I implement this kind of listener to listen to the change/update in database table?

Leem.fin
  • 40,781
  • 83
  • 202
  • 354
  • was that your insert/update by hibernate? – Satheesh Cheveri Dec 17 '13 at 13:08
  • To make that clear: do you expect other services *besides Hibernate* to write to the database or are you looking for a way to execute code when Hibernate writes entities to the database? – mabi Dec 17 '13 at 13:09
  • @mabi , I meant the latter case. I want to execute code when hibernate writes entities to database. I have updated my post for more detailed scenario description. – Leem.fin Dec 17 '13 at 13:12

3 Answers3

0

You can achieve that by writing insert and update triggers.

Triggers can be created on table level. They have nothing to do with which ORM framework you are using. Insert trigger can be configured to fire before an insert. Update trigger can be configured to execute before or after update. Following link provides brief explanation on triggers:

http://docs.oracle.com/cd/B12037_01/appdev.101/b10795/adfns_tr.htm

Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102
0

If the database operation happend through hibernat,you should be able to solve your proble by using Hibernate event listeners

For eg:

public class CreateListner extends DefaultSaveOrUpdateEventListener {

    @Override
    public void onSaveOrUpdate(SaveOrUpdateEvent event) {
       //Do your capturing operation here

        super.onSaveOrUpdate(event);
    }
    }

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/events.html#objectstate-events


Alternatively you can look for Hibernate Interceptor as well

The Interceptor interface provides callbacks from the session to the application, allowing the application to inspect and/or manipulate properties of a persistent object before it is saved, updated, deleted or loaded. One possible use for this is to track auditing information

http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/events.html http://www.mkyong.com/hibernate/hibernate-interceptor-example-audit-log/

Satheesh Cheveri
  • 3,621
  • 3
  • 27
  • 46
0

Personally, I wouldn't recommend using listeners here at all. Your question comes down to adding a timestamp to your student_group table. This question already has code for this. Turns out your join table needs to be either a @Embeddable or two separate @OneToMany relations.

As an example, you can have:

@Entity
public class Student {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
    private List<StudentGroup> groupRels;
}

public class StudentGroup {
    @Id @GeneratedValue
    private Long id;

    @Version
    private DateTime lastChanged;

    @ManyToOne
    private Student student;

    @ManyToOne
    private Group group;
}

Hibernate will update lastChanged with the current time each time the entity gets updated.

If you have that, you can trivially query for StudentGroups that have a timestamp greater then your client's last visit (however you record that) and contain a certain student. If there's such a thing, return the full Student record, else nothing.

I'm not sure, but IIRC Hibernate would update a @Version property even if an element of a mapped property changes, so you could add @Version to your Student and keep the @ManyToMany. But I'm not 100% certain of this - in any case, the separate mapping is the safe choice.


The listener approach would work like in Satheesh Cheveri's answer and just write the records to persistent medium, duplicating them. You'll also have issues with stale entries: what if you record a new role, delete and/or update it and your client comes back? Do you show them your change log - or just the end result?

Community
  • 1
  • 1
mabi
  • 5,279
  • 2
  • 43
  • 78
  • I mean in each of client's request, I need to check whether there is any change/update in database table for this client's data. If there is, I need to send the up-to-date end result of his/her data back as response. If there isn't any changes, I simply send nothing back to client. This is the thing I want to achieve. – Leem.fin Dec 17 '13 at 13:37