-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: How to avoid automatically fetch on ManyToOne
PostPosted: Tue Nov 17, 2015 12:41 pm 
Newbie

Joined: Tue Nov 17, 2015 12:36 pm
Posts: 3
Hello,

I've this simple class (I've reduce properties):
Code:
@Entity
@Immutable
@Table(name = "PERSONA_MUTUA")
public class TestPersonaMutua implements Serializable {


    private static final long serialVersionUID = 1671517730177495806L;

    public TestPersonaMutua() {
    }

    @Id
    @Column(name = "LOGIN")
    private String login;

    @Column(name = "NUSUARIO", nullable = false)
    private Long nusuario;

    @JoinColumn(name = "RESPONSABLE", referencedColumnName = "NUSUARIO", insertable = false, updatable = false)
    @ManyToOne(fetch = FetchType.LAZY)
    private TestPersonaMutua boss;


    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public Long getNusuario() {
        return nusuario;
    }

    public void setNusuario(Long nusuario) {
        this.nusuario = nusuario;
    }

    public TestPersonaMutua getBoss() {
        return boss;
    }

    public void setBoss(TestPersonaMutua boss) {
        this.boss = boss;
    }
}


When I find a TestPersonaMutua without fetching boos I've this bean

TestPersona
- login
- nusuario
- boss
---- login
---- nusuario
---- boss
-------- login
-------- nusuario
-------- boss
...

and so on until the boss 's boss.

Ho can I evict this behaviour? I'm doing something wrong?


Top
 Profile  
 
 Post subject: Re: How to avoid automatically fetch on ManyToOne
PostPosted: Tue Nov 17, 2015 1:59 pm 
Hibernate Team
Hibernate Team

Joined: Fri Sep 09, 2011 3:18 am
Posts: 295
Hi
Hibernate will fetch ManyToOne properties as it cannot use a proxy in case the property is null.

One solution could be to set optional=false on @ManyToOne (if it matches your usecase)

Code:
@ManyToOne(fetch = FetchType.LAZY, optional = false)


Alternatively, you can try checking the configuration property:

Code:
max_fetch_depth

I hope this help,
Davide


Top
 Profile  
 
 Post subject: Re: How to avoid automatically fetch on ManyToOne
PostPosted: Tue Nov 17, 2015 2:11 pm 
Newbie

Joined: Tue Nov 17, 2015 12:36 pm
Posts: 3
What is optional=false? And with the other property can i tell hibernate to fetch only the first fetch?

The field nusuario always has a value.

Lot of thanks,

Marcial


Top
 Profile  
 
 Post subject: Re: How to avoid automatically fetch on ManyToOne
PostPosted: Wed Nov 18, 2015 6:57 am 
Hibernate Team
Hibernate Team

Joined: Fri Sep 09, 2011 3:18 am
Posts: 295
As for the property, you will find many explanation on the web.
I've just picked the first one I've found:
http://stackoverflow.com/questions/25146492/understanding-hibernate-hibernate-max-fetch-depth-and-hibernate-default-batch-fe

Optional = false will tell Hibernate the there is always an association:
http://docs.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html#optional%28%29

Cheers,
Davide


Top
 Profile  
 
 Post subject: Re: How to avoid automatically fetch on ManyToOne
PostPosted: Fri Nov 20, 2015 8:47 am 
Newbie

Joined: Tue Nov 17, 2015 12:36 pm
Posts: 3
Hello,

We've this in persistence.xml:
Code:
<property name="hibernate.max_fetch_depth" value="2"/>
            <property name="hibernate.jdbc.use_scrollable_resultset" value="true"/>
            <property name="hibernate.default_batch_fetch_size" value="100"/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.jdbc.batch_size" value="20"/>
            <property name="hibernate.jdbc.fetch_size" value="100"/>


And we've set optional=false to the property, without luck.

Can we try something else?

Lot of thantks,

Marcial


Top
 Profile  
 
 Post subject: Re: How to avoid automatically fetch on ManyToOne
PostPosted: Wed Nov 25, 2015 11:10 am 
Regular
Regular

Joined: Mon Oct 19, 2015 7:49 am
Posts: 61
Location: ChengDu China
By the way, you can choose to use my framework to do resolve your problem perfectly if you can accept it

Goto https://github.com/babyfish-ct/babyfish to get it,
A functionality called "QueryPath" can resolve your problem perfectly, please view babyfishdemo-spring/../QueryPathTest.java.

OK, Let's discuss your problem, suppose you want to handle all the 3 types of lazy properties supported by ORM:
lazy collection property, lazy reference property and lazy basic property(lazy basic property need bytecode instrument)

(1) Declare JPA Entity class(Also please use the bytecode instrument task of babyfish in the pom.xml)
Code:
@JPAObjectModelInstrument
@Entity
@Table(...)
public class TestPersonaMutua {

   @Id
   @Column(name = "ID")
   private Long id;

   // (1) Lazy ManyToOne, let it to be lazy explicit, because LAZY is not default
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "BOSS_ID")
   private TestPersonaMutua boss;

   // (2) Lazy OneToMany, LAZY is default
   @OneToMany(mappedBy = "boss")
   private Set<TestPersonaMutua> employees;

   // (3) Lazy Basic, supported since Hibernate3, need byte-code instrument.
   @Basic(fetch = FetchType.LAZY)
   @Lob
   @Column(name = "IMAGE")
   private byte[] image;

   @Column(...) //Simple property
   private String name;

   ...getters/setters...
}

(2) Declare the DAO
Code:
@org.springframework.streotype.Repository
public class TestPersonaMutuaDAO {

   @javax.persistence.PersistenceContext
   private org.babyfish.persistence.XEntityManager em; //extends javax.persistence.EntityManager

   // The class "TestPersonaMutua__" whose name ends with TWO(not one) underlines
   // is the typed query path model class whose source code is generated by the Maven plugin of babyfish
   public List<TestPersonaMutua> getTestPersonaMutuas(
      String likeName,

      // 0..any queryPaths, should be specified by UI layer
      // then send it to business logic layer(locally or remotely)
      // finally send it to data access layer(locally or remotely)
      TestPersonaMutua__ ... queryPaths
   ) {
      return this
         .em
         .createQuery("from TestPersonaMutua p where p.name like :likeName", TestPersonaMutua.class)
         .setParemeter("likeName", likeName)
         .setQueryPaths(queryPaths) //Use queryPaths here
         .getResultList();
   }
}


(3) Default query without queryPaths, only query the TestPersonaMutua it self
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas("A");


Only one simple SQL is generated:
Code:
SELECT p.* from TEST_PERSON_MUTUA p where p.NAME like ?


(4) Resolve your problem,
Use FetchPath to fetch all the lazy collection, lazy reference and lazy baisc properties
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas(
   "A",

   // Fetch @ManyToOne for two levels, by adding fetch dynamically
   TestPersonaMutua__.begin().boss().boss().end(),

   // Fetch @OneToMany for two levels, by adding fetch dynamically
   TestPersonaMutua__.begin().employees().employees().end(),

   // Fetch @Basic(fetch = FetchType.LAZY), by generating new SQL statement
   TestPersonaMutua__.begin().image().end(), //Fetch @Basic
);


Two SQL statments are generated,
The first one is used to Query the data and fetch associations
Code:
SELECT p.*
from TEST_PERSON_MUTUA p
left join TEST_PERSON_MUTUA boss
   on p.BOSS_ID = boss.ID // fetch boss
left join TEST_PERSON_MUTUA bossBoss
   on boss.BOSS_ID = bossBoss.ID //fetch boss.boss
left join TEST_PERSON_MUTUA employees
   on p.ID = employees.BOSS_ID // fetch employees
left join TEST_PERSON_MUTUA employeesEmployees
   on employees.ID = employeesEmployees // fetch employees.employees
where p.NAME like ?

The second one is used Fetch the @Basic(fetch = FetchType.LAZY) properties
Code:
SELECT p.ID, p.IMAGE
from TEST_PERSON_MUTUA
where p.ID in (?, ?, ?, ?...?)


(5) DynamicSorting
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas(
   "A",

   TestPersonaMutua__.begin().boss().boss().end(), //Fetch @ManyToOne
   TestPersonaMutua__.begin().employees().employees().end(), //Fetch OneToMany
   TestPersonaMutua__.begin().image().end(), //Fetch @Basic(fetch = FetchType.LAZY),

   // Query result itself should be order by name asc
   TestPersonaMutua__.preOrderBy().name().asc(),

   // The collection association "this.employees" should be order by name desc
   TestPersonaMutua__.preOrderBy().employees().name().desc(),
   TestPersonaMutua__.preOrderBy().employees().employees().name().desc()
);


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.