2

I'm implementing the soft delete logic for my entities using Spring and Hibernate. I use @Filter Hibernate annotation to perform this logic. But there is a problem I cannot resolve: the objects in lazy loaded collections are not being filtered.

The code is quite simple:

@Entity
@Table(name = "orders")
public class Order { 

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
  @Filter(name = "deletedOrderItemFilter", condition = "0 = deleted")
  private Set<OrderItem> orderItems;    

  // getter and setter
}

@Entity
@Table(name = "order_item")
@FilterDef(name = "deletedOrderItemFilter", defaultCondition = "0 = deleted")
public class OrderItem {

  @ManyToOne
  @JoinColumn(name = "orderId", nullable = false)
  private Order order;

  @Column(name = "deleted")
  private boolean deleted;

  // getters and setters
}

So the logic is "when opening an Order object don't show removed OrderItems" Here is the method in DAO which returns the Session object. The Session factory is Spring's org.springframework.orm.hibernate4.LocalSessionFactoryBean.

public Session getSession() {
  Session session = sessionFactory.getCurrentSession();
  session.enableFilter("deletedOrderItemFilter");
  return session;
}

So this method is being called only explicitly - when I request the List of Orders. But what's interesting is that the PersistenceSet for my orderItems List seems to have a null Session (it's strange 'cause I am not getting any LazyInitializationException). So the filter "deletedOrderItemFilter" is not applied to the orderItems List.

I've googled it of course and I've found out that as soon as the Transaction in which I get the Orders List is closed, the Session is closed too. But still I cannot find any solution. I've tried to explicitly assign a new temporary Session to the PersistenceSet (when fetching it) but still no luck (although the session factory seemed to have my filter in the filters list).

Any help would be appreciated.

UPDATE OK I can solve it the "dirty" way:

  • OrderItem implemets my own interface Removable with method like isRemoved
  • in the orderItems getter call common filtering method iterating through the items and filtering them. The downside is that I would have to load all the objects - deleted and not - from the database.

UPDATE I'm not getting any LazyInitializationException because of the sessionFactory Spring bean config property:

<prop key="hibernate.enable_lazy_load_no_trans">true</prop>

So I guess: no transaction - no session - no filters applied.

alexbt
  • 16,415
  • 6
  • 78
  • 87
iozee
  • 1,339
  • 1
  • 12
  • 24
  • 1
    I'd say it's better to move a deleted row to a new table, like foo_history. This is what Hibernate Envers does. – Neil McGuigan Mar 15 '15 at 19:14
  • @NeilMcGuigan thanks, I'll check it out. Actually, I use Envers in my project and maybe it will be enough for my purposes. – iozee Mar 15 '15 at 20:51

0 Answers0