java - onetoone - mode lazy hibernate




Diferença entre FetchType LAZY e EAGER na Java Persistence API? (9)

Eu sou um novato em Java Persistence API e Hibernate.

Qual é a diferença entre FetchType.LAZY e FetchType.LAZY na Java Persistence API?


enum público FetchType estende java.lang.Enum Define estratégias para buscar dados do banco de dados. A estratégia EAGER é um requisito no tempo de execução do provedor de persistência que os dados devem ser avidamente buscados. A estratégia LAZY é uma dica para o tempo de execução do provedor de persistência que os dados devem ser buscados de forma preguiçosa quando forem acessados ​​pela primeira vez. A implementação tem permissão para buscar ansiosamente dados para os quais a dica da estratégia LAZY foi especificada. Exemplo: @Basic (fetch = LAZY) protegido String getName () {return name; }

Source


Às vezes você tem duas entidades e há uma relação entre elas. Por exemplo, você pode ter uma entidade chamada Universidade e outra entidade chamada Estudante.

A entidade da universidade pode ter algumas propriedades básicas, como id, nome, endereço etc., bem como uma propriedade chamada students:

public class University {
 private String id;
 private String name;
 private String address;
 private List<Student> students;

 // setters and getters
}

Agora, quando você carrega uma universidade do banco de dados, a JPA carrega seus campos id, name e address para você. Mas você tem duas opções para os alunos: carregá-la junto com o restante dos campos (ou seja, ansiosamente) ou carregá-la sob demanda (ou seja, preguiçosamente) quando você chama o método getStudents () da universidade.

Quando uma universidade tem muitos alunos, não é eficiente carregar todos os seus alunos quando não são necessários. Portanto, em casos semelhantes, você pode declarar que deseja que os alunos sejam carregados quando realmente forem necessários. Isso é chamado de carregamento lento.


Basicamente,

LAZY = fetch when needed
EAGER = fetch immediately

De acordo com o meu conhecimento, o tipo de busca depende da sua necessidade.

FetchType.LAZY está sob demanda (ou seja, quando solicitamos os dados).

FetchType.EAGER é imediato (ou seja, antes de nosso requisito chegar, estamos buscando desnecessariamente o registro)


Eu posso considerar o desempenho e a utilização da memória. Uma grande diferença é que a estratégia de busca EAGER permite usar objetos de dados buscados sem sessão. Por quê?
Todos os dados são buscados quando dados marcados como ansiosos no objeto quando a sessão é conectada. No entanto, em caso de estratégia de carregamento lento, o carregamento lento do objeto marcado não recuperará dados se a sessão for desconectada (após a instrução session.close() ). Tudo o que pode ser feito pelo proxy de hibernação. Ansiosa estratégia permite que os dados ainda estejam disponíveis após a sessão de encerramento.


LAZY: Ele busca as entidades filhas preguiçosamente, ou seja, na hora de buscar a entidade pai, ele busca apenas o proxy (criado pelo cglib ou qualquer outro utilitário) das entidades filhas e quando você acessa qualquer propriedade da entidade filho, ele é buscado pelo hibernate.

ÁGURO: busca as entidades infantis junto com os pais.

Para entender melhor, vá para a documentação do Jboss ou você pode usar hibernate.show_sql=true para seu aplicativo e verificar as consultas emitidas pelo hibernate.


Por padrão, para todos os objetos de coleção e mapa, a regra de busca é FetchType.LAZY e, para outras instâncias, segue a política FetchType.EAGER .
Em resumo, as relações @ManyToMany e @ManyToMany não buscam os objetos relacionados (coleção e mapa) de maneira implícita, mas a operação de recuperação é colocada em cascata através do campo em @OneToOne e @OneToOne .

(cortesia: - objectdbcom)


Tanto FetchType.LAZY quanto FetchType.EAGER são usados ​​para definir o plano de FetchType.EAGER padrão .

Infelizmente, você só pode sobrescrever o plano de busca padrão para a busca do LAZY. A busca do EAGER é menos flexível e pode levar a muitos problemas de desempenho .

Meu conselho é restringir o impulso de tornar suas associações EAGER, pois buscar é uma responsabilidade de tempo de consulta. Portanto, todas as suas consultas devem usar a diretiva de busca para recuperar apenas o que é necessário para o caso de negócios atual.


Book.java

        import java.io.Serializable;
        import javax.persistence.Column;
        import javax.persistence.Entity;
        import javax.persistence.GeneratedValue;
        import javax.persistence.GenerationType;
        import javax.persistence.Id;
        import javax.persistence.ManyToOne;
        import javax.persistence.Table;

        @Entity
        @Table(name="Books")
        public class Books implements Serializable{

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="book_id")
        private int id;
        @Column(name="book_name")
        private String name;

        @Column(name="author_name")
        private String authorName;

        @ManyToOne
        Subject subject;

        public Subject getSubject() {
            return subject;
        }
        public void setSubject(Subject subject) {
            this.subject = subject;
        }

        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAuthorName() {
            return authorName;
        }
        public void setAuthorName(String authorName) {
            this.authorName = authorName;
        }

        }

Subject.java

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue; 
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    @Entity
    @Table(name="Subject")
    public class Subject implements Serializable{

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="subject_id")
    private int id;
    @Column(name="subject_name")
    private String name;
    /**
    Observe carefully i have mentioned fetchType.EAGER. By default its is fetchType.LAZY for @OneToMany i have mentioned it but not required. Check the Output by changing it to fetchType.EAGER
    */

    @OneToMany(mappedBy="subject",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
    List<Books> listBooks=new ArrayList<Books>();

    public List<Books> getListBooks() {
        return listBooks;
    }
    public void setListBooks(List<Books> listBooks) {
        this.listBooks = listBooks;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    }

HibernateUtil.java

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {

 private static SessionFactory sessionFactory ;
 static {
    Configuration configuration = new Configuration();
    configuration.addAnnotatedClass (Com.OneToMany.Books.class);
    configuration.addAnnotatedClass (Com.OneToMany.Subject.class);
    configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
    configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");                                
    configuration.setProperty("hibernate.connection.username", "root");     
    configuration.setProperty("hibernate.connection.password", "root");
    configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
    configuration.setProperty("hibernate.hbm2ddl.auto", "update");
    configuration.setProperty("hibernate.show_sql", "true");
    configuration.setProperty(" hibernate.connection.pool_size", "10");
    configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
    configuration.setProperty(" hibernate.cache.use_query_cache", "true");
    configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
    configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");

   // configuration
    StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
    sessionFactory = configuration.buildSessionFactory(builder.build());
 }
public static SessionFactory getSessionFactory() {
    return sessionFactory;
}
} 

Main.java

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;

    public class Main {

    public static void main(String[] args) {
        SessionFactory factory=HibernateUtil.getSessionFactory();
        save(factory);
        retrieve(factory);

    }

     private static void retrieve(SessionFactory factory) {
        Session session=factory.openSession();
        try{
            session.getTransaction().begin();
            Subject subject=(Subject)session.get(Subject.class, 1);
            System.out.println("subject associated collection is loading lazily as @OneToMany is lazy loaded");

            Books books=(Books)session.get(Books.class, 1);
            System.out.println("books associated collection is loading eagerly as by default @ManyToOne is Eagerly loaded");
            /*Books b1=(Books)session.get(Books.class, new Integer(1));

            Subject sub=session.get(Subject.class, 1);
            sub.getListBooks().remove(b1);
            session.save(sub);
            session.getTransaction().commit();*/
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            session.close();
        }

        }

       private static void save(SessionFactory factory){
        Subject subject=new Subject();
        subject.setName("C++");

        Books books=new Books();
        books.setAuthorName("Bala");
        books.setName("C++ Book");
        books.setSubject(subject);

        subject.getListBooks().add(books);
        Session session=factory.openSession();
        try{
        session.beginTransaction();

        session.save(subject);

        session.getTransaction().commit();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            session.close();
        }
    }

    }

Verifique o método retrieve () de Main.java. Quando chegarmos a Subject, a lista de colecções Books , anotada com @OneToMany , será carregada preguiçosamente. Mas, por outro lado, Books relacionou associação de assunto de coleção, anotado com @ManyToOne, carrega eargerly (por [default][1] para fetchType=EAGER , fetchType=EAGER ). Podemos mudar o comportamento colocando fetchType.EAGER em @OneToMany Subject.java ou fetchType.LAZY em @ManyToOne em Books.java.





java-persistence-api