2

I know that similar questions have already been asked for plenty of times but I haven't found one that could help me.

So, could I ask you to help me to find the cause of why a Book's title is fetched EAGERly?

I have a very simple codebase, here is my entity:

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class Book {

    @Id
    @GeneratedValue
    private int id;

    @Lob
    @Basic(fetch = FetchType.LAZY, optional = false)
    private String title;

}

And here is a client piece of code, in this case represented by psvm():

public static void main(String[] args) {

    final ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    final SessionFactory sessionFactory = context.getBean(SessionFactory.class);
    Session session = sessionFactory.openSession();

    Book book = Book.builder().title("Peace and War").build();

    Transaction tx = session.beginTransaction();
    session.save(book);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    book = session.get(Book.class, book.getId());
}

I've also added a plugin to maven in order to enhance bytecode:

   <build>
        <plugins>
            <plugin>
                <groupId>org.hibernate.orm.tooling</groupId>
                <artifactId>hibernate-enhance-maven-plugin</artifactId>
                <version>5.3.6.Final</version>
                <executions>
                    <execution>
                        <configuration>
                            <enableLazyInitialization>true</enableLazyInitialization>
                        </configuration>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
   </build>

But still, the title is fetched eagerly with the following query:

Hibernate: select book0_.id as id1_0_0_, book0_.title as title2_0_0_ from Book book0_ where book0_.id=?

that I can see because of hibernate.show_sql=true

Could you help me to figure out what I am doing wrong? Seems that the answer is on the surface but I can't spot it.

6
  • Would this stackoverflow.com/questions/43749821/… help_ Commented Sep 3, 2018 at 17:55
  • 1
    If you use FetchType.LAZY, doesn't the linked object have to be annotated with @Entity? i.e. you can't use it with String. It doesn't make sense to use it with a String, otherwise there is no scenario when you would actually fetch it other than when retrieving the main object, in this case Book. Commented Sep 3, 2018 at 17:58
  • 2
    Lazy fetching on simple types (i.e. primitives, their wrappers, string etc.) might not be supported. That normally doesn't make much sense anyways. Commented Sep 3, 2018 at 17:59
  • Why Hibernate simply can't create a proxy of an Entity class to provide lazy loading for wrappers, string etc? Commented Sep 3, 2018 at 18:01
  • 1
    In most cases loading properties lazily doesn't make much sense as you'd need more queries to get the properties and if you only are interested in a few of them you can always use a query like select book.id from Book book ... instead. Commented Sep 3, 2018 at 18:04

1 Answer 1

3
 @Basic(fetch = FetchType.LAZY, optional = false)

According to the JPA specification @Basic Lazy loading is not guaranteed to be applied regarding which implementation you are using. you can check it here https://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes

Support for LAZY fetching on Basic is optional in JPA, so some JPA providers may not support it.

Anyway, one workaround is to create a new separated entity, say for example BookTitle, then establish a one-to-one relation and load it Lazily from the Book Entity:

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

    @Lob
    @Basic(fetch = FetchType.LAZY, optional = false)
    private String title;
}


public class Book {

    @Id
    @GeneratedValue
    private int id;

    @OneToOne (fetch = FetchType.LAZY)
    private BookTitle bookTitle;

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.