Como se ha dicho
quiero una solución que puedo controlar lo que se carga con pereza cuando realizo la consulta
Si usted tiene un mapeo como éste
@Entity
public class GiftCard implements Serializable {
private User buyer;
@ManyToOne
@JoinColumn(name="buyerUserId")
public User getBuyer() {
return this.buyer;
}
}
Cualquier relación * ToOne, como @OneToOne y @ManyToOne, es, de forma predeterminada, FetchType.EAGER lo que significa que será una siempre fue a buscar. Pero, no podría ser lo que quieres. Lo que dices como Puedo controlar lo que está cargado perezosamente se puede traducir como Obteniendo Estrategia. POJO in Action libro es compatible con un patrón como este (firma del método Aviso)
public class GiftCardRepositoryImpl implements GiftCardRepository {
public List<GiftCard> findGiftCardWithBuyer() {
return sessionFactory.getCurrentSession().createQuery("from GiftCard c inner join fetch c.buyer where c.recipientNotificationRequested = 1").list();
}
}
Así que basado en su caso de uso, puede crear su propio encontrar ... Con ... Y ... método. Se encargará de buscar exactamente lo que quiere
Pero tiene un problema: no es compatible con la firma de un método genérico. Para cada repositorio de @Entity, debe definir su método de búsqueda personalizado ... Con ... Y. Debido a eso, les muestro cómo definir un repositorio genérico
public interface Repository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> {
void add(INSTANCE_CLASS instance);
void remove(PRIMARY_KEY_CLASS id);
void update(PRIMARY_KEY_CLASS id, UPDATABLE_INSTANCE_CLASS updatableInstance);
INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id);
INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, FetchingStrategy fetchingStrategy);
List<INSTANCE_CLASS> findAll();
List<INSTANCE_CLASS> findAll(FetchingStrategy fetchingStrategy);
List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize);
List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, FetchingStrategy fetchingStrategy);
List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria);
List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, FetchingStrategy fetchingStrategy);
List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria);
List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, FetchingStrategy fetchingStrategy);
}
Pero, a veces , que no desea que todos los métodos definidos por la interfaz de repositorio genérico. Solución: cree una clase de AbstractRepository que implementará un repositorio ficticio.Spring Framework, por ejemplo, en gran medida el uso de este tipo de patrón Interfaz >> AbstractInterface
public abstract class AbstractRepository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> implements Repository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> {
public void add(INSTANCE_CLASS instance) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void remove(PRIMARY_KEY_CLASS id) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void update(PRIMARY_KEY_CLASS id, UPDATABLE_INSTANCE_CLASS updatableInstance) {
throw new UnsupportedOperationException("Not supported yet.");
}
public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id) {
throw new UnsupportedOperationException("Not supported yet.");
}
public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, FetchingStrategy fetchingStrategy) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAll() {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAll(FetchingStrategy fetchingStrategy) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, FetchingStrategy fetchingStrategy) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, FetchingStrategy fetchingStrategy) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria) {
throw new UnsupportedOperationException("Not supported yet.");
}
public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, FetchingStrategy fetchingStrategy) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Así que su GiftCardRepository se puede volver a escribir como (Ver extiende en lugar de implementos) y simplemente anula lo que realmente quiere
public class GiftCardRepository extends AbstractRepository<GiftCard, GiftCard, String> {
public static final GIFT_CARDS_WITH_BUYER GIFT_CARDS_WITH_BUYER = new GIFT_CARDS_WITH_WITH_BUYER();
public static final GIFT_CARDS_WITHOUT_NO_RELATIONSHIP GIFT_CARDS_WITHOUT_NO_RELATIONSHIP = new GIFT_CARDS_WITHOUT_NO_RELATIONSHIP();
public List<GiftCard> findAll(FetchingStrategy fetchingStrategy) {
sessionFactory.getCurrentSession().getNamedQuery(fetchingStrategy.toString()).list();
}
/**
* FetchingStrategy is just a marker interface
* public interface FetchingStrategy {}
*
* And AbstractFetchingStrategy allows you to retrieve the name of the Fetching Strategy you want, by overriding toString method
* public class AbstractFetchingStrategy implements FetchingStrategy {
*
* @Override
* public String toString() {
* return getClass().getSimpleName();
* }
*
* }
*
* Because there is no need to create an instance outside our repository, we mark it as private
* Notive each FetchingStrategy must match a named query
*/
private static class GIFT_CARDS_WITH_BUYER extends AbstractFetchingStrategy {}
private static class GIFT_CARDS_WITHOUT_NO_RELATIONSHIP extends AbstractFetchingStrategy {}
}
Ahora exteriorizan nuestra consulta con nombre en una línea múltiple - y legible y mantenible - archivo XML
// app.hbl.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<query name="GIFT_CARDS_WITH_BUYER">
<![CDATA[
from
GiftCard c
left join fetch
c.buyer
where
c.recipientNotificationRequested = 1
]]>
</query>
<query name="GIFT_CARDS_WITHOUT_NO_RELATIONSHIP">
<![CDATA[
from
GiftCard
]]>
</query>
</hibernate-mapping>
lo tanto, si desea recuperar usted tarjeta de regalo con el Comprador, simplemente llame
Repository<GiftCard, GiftCard, String> giftCardRepository;
List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITH_WITH_BUYER);
Y para recuperar nuestra tarjeta de regalo y sin ninguna relación, simplemente llame
List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITHOUT_NO_RELATIONSHIP);
o el uso de importación estática
import static packageTo.GiftCardRepository.*;
Y
List<GiftCard> giftCardList = giftCardRepository.findAll(GIFT_CARDS_WITHOUT_NO_RELATIONSHIP);
¡Espero que pueda ser útil para usted!
Muy interesante ... esta es una gran fuente de reflexión. Y trae a colación una pregunta secundaria. ¿Cómo realizaría una consulta que no capta ningún objeto asociado que no sea la GiftCard de destino? –
@ Ben Benson Ver GiftCardRepository (última línea), nombre de archivo de consulta y código adicional en la parte inferior. Si mi respuesta cumple con sus necesidades, márquela como aceptada. Gracias –