Suporte ao Plano de Carregamento do EntityManager

Um FetchPlan é a estratégia que o gerenciador de entidade usa para recuperar objetos associados se o aplicativo precisar acessar relacionamentos.

Exemplo

Suponha, por exemplo, que seu aplicativo tenha duas entidades: Department e Employee. O relacionamento entre a entidade Department e a entidade Employee é um relacionamento bidirecional um-para-muitos: Um departamento tem vários funcionários, e um funcionário pertence a um único departamento. Como na maioria das vezes, quando é feita uma busca pela entidade Department, seus Employees provavelmente são buscados, e o tipo de busca desse relacionamento um-para-muitos é configurado como EAGER.

Aqui está um fragmento da classe Department.

	@Entity
public class Department {

    @Id
    private String deptId;

    @Basic
    String deptName;

		@OneToMany(fetch = FetchType.EAGER, mappedBy="department", cascade
= {CascadeType.PERSIST})
		public Collection<Employee> employees;

}

Em um ambiente distribuído, quando um aplicativo chama em.find(Department.class, "dept1") para localizar uma entidade Department com a chave "dept1", essa operação find obtém a entidade Department e todas as suas relações eager-fetched. No caso do fragmento anterior, elas são todos os funcionários do departamento "dept1".

Antes do WebSphere eXtreme Scale 6.1.0.5, a recuperação de uma entidade Department e N entidades Employee incorria em N+1 trips de cliente-servidor porque o cliente recuperava uma entidade para um trip de cliente-servidor. É possível melhorar o desempenho se você recuperar essas N+1 entidades em um trip.

Plano de Carregamento

Um plano de carregamento pode ser utilizado para customizar a forma como você executa um carregamento ansioso de relacionamentos customizando a profundidade máxima dos relacionamentos. A profundidade da busca substitui relações eager maiores do que a profundidade especificada para relações lazy. Por padrão, a profundidade da busca é a profundidade máxima da busca. Isso significa que relacionamentos eager de todos os níveis navegáveis como eager a partir da entidade raiz serão buscados. Um relacionamento EAGER é navegável como eager a partir de uma entidade raiz se, e apenas se, todas as relações começando da entidade raiz para ela forem configuradas como eager-fetched.

No exemplo anterior, a entidade Employee é navegável como eager a partir da entidade Department porque o relacionamento Department-Employee é configurado como eager-fetched.

Se a entidade Employee tiver outro relacionamento eager com uma entidade Address, por exemplo, a entidade Address também será navegável como eager a partir da entidade Department. Entretanto, se os relacionamentos Department-Employee foram configurados como lazy-fetch, a entidade Address não será navegável como eager a partir da entidade Department, pois o relacionamento Department-Employee quebra a cadeia de eager fetch.

Um objeto Plano de Carregamento pode ser recuperado da instância EntityManager. O aplicativo pode utilizar o método setMaxFetchDepth para alterar a profundidade máxima da busca.

Um plano de carregamento é associado a uma instância EntityManager. O plano de carregamento aplica-se a qualquer operação de busca, mais especificamente da seguinte forma.

O objeto Plano de Carregamento é mutável. Após ser alterado, o valor será aplicado às operações de busca executadas posteriormente.

Um plano de carregamento é importante para uma implementação distribuída porque decide se as entidades de relacionamento eager-fetched são recuperadas com a entidade raiz em um trip de cliente/servidor ou em mais de uma.

Continuando com o exemplo anterior, considere que o plano de carregamento tenha profundidade máxima configurada como infinito. Nesse caso, quando o aplicativo chama em.find(Department.class, "dept1") para localizar Department, essa operação find obtém uma entidade Department e N entidades Employee em um trip de cliente/servidor. Entretanto, para um plano de carregamento com profundidade de busca máxima configurada como zero, apenas o objeto Department será recuperado do servidor, enquanto as entidades Employee são recuperadas do servidor apenas quando a coleta de Employees do objeto Department é acessada.

Planos de Carregamento Diferentes

Você tem diferentes planos de carregamentos baseados em seus requisitos, explicados nas seguintes seções.

Impacto em uma grade distribuída

Importante: Se um relacionamento for solicitado, utilizando configuração ou anotação OrderBy, ele será considerado um relacionamento eager, mesmo que esteja configurado como lazy-fetch.

Considerações de Desempenho em um Ambiente Distribuído

Por padrão, todos os relacionamentos navegáveis como eager a partir da entidade raiz serão recuperados em um trip de cliente/servidor. Isso pode melhorar o desempenho se todos os relacionamentos forem utilizados. No entanto, em certos cenários de uso, nem todos os relacionamentos navegáveis como eager a partir da entidade raiz são utilizados, portanto eles incorrem em gasto adicional de tempo de execução e em gasto adicional de largura de banda ao recuperar essas entidades não utilizadas.

Para esses casos, o aplicativo pode configurar a profundidade de busca máxima para um número pequeno para diminuir a profundidade de entidades a serem recuperadas, tornando lazy todas as relações eager após essa profundidade específica. Essa configuração pode melhorar o desempenho.

Continuando com o exemplo Department-Employee-Address anterior, por padrão, todas as entidades Address associadas a employees de Department "dept1" serão recuperadas quando em.find(Department.class, "dept1") for chamado. Se o aplicativo não utilizar entidades Address, ele poderá configurar a profundidade máxima da busca como 1, portanto as entidades Address não serão recuperadas com a entidade Department.