msmani
msmani

Reputation: 720

Hibernate override "lazy=false"

I am working on a new module in an existing project. The project already has a user table, a pojo and a corresponding mapping file. The problem is that they are fetching all the properties eagerly by mentioning lazy="false". But, in my module, I am doing lot of read & write in a single request, so I don't want to fetch eagerly. What I want to know is that, is it possible to create an another mapping file for the same table & same pojo to load all the properties lazily? I have tried by assigning different entity-name for the mapping files, but while deploying, I am getting the error "Repeated column in mapping for entity".

I saw this answer, but it says "do not map child", then how will I get the proxies?

Upvotes: 9

Views: 5596

Answers (5)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 154090

That's one major drawback for using EAGER fetching as the default strategy. Usually you'd have a LAZY children collection that you can eagerly fetch on a HQL query basis.

What's worth mentioning is that HQL/Criteria queries overrule the default fetch strategy (the one given by your entity mappings) so that you can explicitly specify what to fetch.

For Criteria queries, you might give a try to Criteria.setFetchMode FetchMode.LAZY, although it's deprecated.

Another way to overrule the EAGER fetching is to use a javax.persistence.fetchgraph. This way, you can specify what you want to fetch and all the EAGER fetching properties that were not included in the Entity Graph are going to be fetched lazily.

Upvotes: 3

Andreas Covidiot
Andreas Covidiot

Reputation: 4765

Some other approaches mentioned we used based on JPA inheritance (@MappedSuperclass) and/or database views and examplified with the following pseudo code (it works both ways for EAGER->LAZY or LAZY->EAGER scenarios):

@Table( name = "table_x" )
@Entity
class DaoX { @...( fetch = FetchType.EAGER ) refY ;  /* ... other stuff ... */ }
  • our DaoX used e.g. in other code like this:

    DaoX x ;
    
    @Entity
    class DaoZ {  DaoX x ; }
    

via inheritance

so if we would like to have it lazily loaded we could pimp the inheritance hierarchy up like this with only minimal additional code:

@Table( name = "table_x" )
@MappedSuperclass
class abstract BaseDaoX { /* ... other stuff ... */ }

@Entity
class DaoX extends BaseDaoX { @...( fetch = FetchType.EAGER ) refY ; }

@Entity
class DaoXLazy extends BaseDaoX { @...( fetch = FetchType.LAZY ) refY ; }
  • our DaoX usages should be substituted by BaseDaoX where possible (no direct JPA mapping)

    BaseDaoX x ;
    
    @Entity
    class DaoZ {  DaoX x ; }
    
    @Entity
    class DaoZLazy {  DaoXLazy x ; }
    

so you can use DaoXLazy or DaoZLazy for your desired scenarios.

via views (in LAZY->EAGER scenarios)

(if you can change your current EAGER to LAZY which is generally more appropriate) you could just map your (maybe deeply nested) lazy stuff with minimal load e.g. like this ( we like to load prop_f1 and prop_b1 here )

-- db view:
create or replace view view_x_eager as
select 
  tx.*,
  f.prop_f1,
  b.prop_b1
from table_x                 tx
  -- assuming tx:f ~ 1:1 and f:b ~ 1:1 for simplicity here:
  left outer join table_foo  f  on ( f.id = tx.foo_id )
  left outer join table_bar  b  on ( b.id = f.bar_id  )

@Table( name = "view_x_eager" )
class DaoXEager extends BaseDaoX { 
  @...( fetch = FetchType.EAGER ) refY ; 

  String prop_f1 ;
  String prop_b1 ;
}

Upvotes: 0

Arkantos
Arkantos

Reputation: 6608

Like Vlad Mihalcea said, use Criteria API it will work. I've tried it :)

Criteria c =  session.createCriteria(YourHibernateClass.class);
c.setFetchMode(urLazyPropName,FetchMode.LAZY);

Atleast this you can do with out changing existing hbm files

Upvotes: 0

Deltharis
Deltharis

Reputation: 2373

The point Hibernate mapping setting lazy = 'false' is making, is that you can map the same table twice if you use two different java classes. In your case, if you know for a fact that setting lazy="true" will suffice:

  1. create empty subclass of your pojo
  2. map your subclass the way you want to the same user table (for examply copy-pasting the existing mapping and changing lazy property value)
  3. in the module you create only use the subclass

Upvotes: 1

Rudra21
Rudra21

Reputation: 342

I think, your question is to not to load associated entity , egarly ? for this when : FetchType.LAZY = Doesn’t load the relationships unless explicitly called via getter. FetchType.EAGER = Loads ALL relationships default

In your case , if my understanding is correct then use lazy="false" fetch="select" so it will select on demand via getter. check this url , it will give more clear idea : Hibernate XML Mapping: Lazy False or Fetch Select? A Short Primer On Fetching Strategies

Upvotes: 2

Related Questions