Chapter 13. Filtering data

 

In this chapter

  • Cascading state transitions
  • Listening to and intercepting events
  • Auditing and versioning with Hibernate Envers
  • Filtering data dynamically

In this chapter, you see many different strategies for filtering data as it passes through the Hibernate engine. When Hibernate loads data from the database, you can transparently restrict the data seen by the application with a filter. When Hibernate stores data in the database, you can listen to such an event and execute some secondary routines: for example, write an audit log or assign a tenant identifier to the record.

We explore the following data-filtering features and APIs:

13.1. Cascading state transitions

Path: /model/src/main/java/org/jpwh/model/filtering/cascade/Item.java

@Entity
public class Item {
<enter/>
    @OneToMany(
        mappedBy = "item",
        cascade = {CascadeType.DETACH, CascadeType.MERGE}
    )
    protected Set<Bid> bids = new HashSet<Bid>();
<enter/>
    // ...
}

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

item.setName("New Name");
<enter/>
Bid bid = new Bid(new BigDecimal("101.00"), item);
item.getBids().add(bid);

Path: /model/src/main/java/org/jpwh/model/filtering/cascade/Bid.java

@Entity
public class Bid {
<enter/>
    @Override
    public boolean equals(Object other) {
        if (this == other) return true;
        if (other == null) return false;
        if (!(other instanceof Bid)) return false;
        Bid that = (Bid) other;
<enter/>
        if (!this.getAmount().equals(that.getAmount()))
            return false;
        if (!this.getItem().getId().equals(that.getItem().getId()))
            return false;
        return true;
    }
<enter/>
    @Override
    public int hashCode() {
        int result = getAmount().hashCode();
        result = 31 * result + getItem().getId().hashCode();
        return result;
    }
<enter/>
    // ...
}

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

Path: /model/src/main/java/org/jpwh/model/filtering/cascade/User.java

@Entity
@Table(name = "USERS")
public class User {
<enter/>
    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "USER_ID", nullable = false)
    protected Set<BillingDetails> billingDetails = new HashSet<>();
<enter/>
    // ...
}

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

Path: /model/src/main/java/org/jpwh/model/filtering/cascade/Item.java

@Entity
public class Item {
<enter/>
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SELLER_ID", nullable = false)
    @org.hibernate.annotations.Cascade(
        org.hibernate.annotations.CascadeType.REPLICATE
    )
    protected User seller;
<enter/>
    // ...
}

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

Path: /examples/src/test/java/org/jpwh/test/filtering/Cascade.java

tx.begin();
EntityManager otherDatabase = // ... get EntityManager
<enter/>
otherDatabase.unwrap(Session.class)
    .replicate(item, ReplicationMode.OVERWRITE);
// select ID from ITEM where ID = ?
// select ID from USERS where ID = ?
<enter/>
tx.commit();
// update ITEM set NAME = ?, SELLER_ID = ?, ... where ID = ?
// update USERS set USERNAME = ?, ... where ID = ?
otherDatabase.close();

13.2. Listening to and intercepting events

sitemap