utilizadas tutorial tipos por lazy joins inner consultas hibernate spring-data-jpa

tutorial - tipos de consultas utilizadas por hibernate



cómo realizar una carga perezosa cuando se utiliza spring-data-jpa, con hibernación, desde una aplicación de consola (3)

Esto funcionó para mí:

@Component public class Test { @Inject OrderDAO orderDAO; @PersistenceUnit private EntityManagerFactory emf; @PostConstruct public void test(){ EntityManager em= emf.createEntityManager(); for (Order o:orderDAO.findAll()){ o=em.find(o.getClass(),o.getId()); System.out.println(o.getLazyField()); } em.close(); } }

Tengo una aplicación de consola pequeña y estoy usando spring-data-jpa con hibernate. Realmente no puedo encontrar la forma de inicializar las colecciones de forma perezosa al utilizar spring-data-jpa con sus repositorios, en una aplicación de consola independiente. Aquí está algo de mi código:

@Entity public class User { ... @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="USER_ORDER_ID") private Set<Order> orders = new HashSet<Order>(); ... }

repositorio:

public interface UserRepository extends PagingAndSortingRepository<User, Long> { public ArrayList<User> findByFirstNameIgnoreCase(String firstName); }

servicio implícito:

@Service @Repository @Transactional public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; public ArrayList<User> findByFirstNameIgnoreCase(String firstName) { ArrayList<User> users = new ArrayList<User>(); users = userRepository.findByFirstNameIgnoreCase(firstName); return users; }

mi principal método:

... user = userRepository.findByFirstNameIgnoreCase("john").get(0); orders = user.getOrders(); for (Order order : orders) { LOGGER.info("getting orders: " + order.getId()); }

el bucle foreach obtiene una excepción:

EVERE: no se pudo inicializar perezosamente una colección de roles: com.aki.util.User.orders, no se cerró ninguna sesión o sesión org.hibernate.LazyInitializationException: no se pudo inicializar perezosamente una colección de roles:

Tenga en cuenta que no tengo este problema al ejecutar esto desde una aplicación web con algún tipo de OpenSessionInViewFilter.


Sin embargo, encontré un camino. Este método está dentro de mi implementación de servicio:

public Set<Order> fetchUserOrders(Long userId) { User user = userRepository.findOne(userId); Hibernate.initialize(user.getOrders()); Set<Order> orders = user.getOrders(); return orders; }

Nota: esto es como @zagyi sugirió en uno de sus comentarios, pero también preste atención a la declaración: Hibernate.initialize(user.getOrders()); sin esto, la colección aún no se inicializará y obtendrá un error.


Una solución puede ser hacer de User.orders una colección ansiosamente User.orders por

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER) private Set<Order> orders = new HashSet<Order>();

Las asociaciones de entidades se cargan perezosamente por defecto. Esto significa que el conjunto de orders es en realidad solo un objeto proxy que no se inicializará hasta que invoque un método en él. Esto es bueno, porque los objetos de Order asociados no se cargarán a menos que sean necesarios. Sin embargo, esto puede causar problemas, si intenta acceder a la colección sin inicializar fuera de una transacción en ejecución.

Si sabe que, en la mayoría de los casos, necesitará las Órdenes del Usuario, tiene sentido hacer la asociación con entusiasmo. De lo contrario, deberá asegurarse de que la recopilación se inicialice / cargue dentro de una transacción. El OpenSessionInViewFilter que mencionó se asegura de que la transacción permanezca abierta durante el procesamiento de la solicitud, es por eso que no tiene este problema en su aplicación web.

En caso de que deba mantenerlo cargado perezosamente, intente utilizar la plantilla de TransactionTemplate de Spring para ajustar el código en su método principal:

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { ... } });