Wie gesagt
ich eine Lösung wollen, die ich kontrollieren kann, was faul geladen wird, wenn ich die Abfrage ausführen
Wenn Sie eine Abbildung wie diese haben ein
@Entity
public class GiftCard implements Serializable {
private User buyer;
@ManyToOne
@JoinColumn(name="buyerUserId")
public User getBuyer() {
return this.buyer;
}
}
Jede * ToOne-Beziehung, wie z. B. @OneToOne und @ManyToOne, ist standardmäßig FetchType.EAGER, was bedeutet, dass es ein a Immer geholt. Aber es könnte nicht sein, was du willst. Was du sagst als Ich kann kontrollieren, was lazy geladen wird kann übersetzt werden als Abrufen der Strategie. POJO in Action Buch unterstützt ein Muster wie dieses (Hinweis Methodensignatur)
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();
}
}
auf Ihren Anwendungsfall So basiert, können Sie Ihre eigenen finden ... Mit ... Und ... Methode erstellen. Es wird sich darum kümmern, zu holen, was Sie wollen
Aber es hat ein Problem: Es unterstützt keine generische Methode Signatur. Für jedes @Entity-Repository müssen Sie Ihre benutzerdefinierte Methode finden ... mit ... und definieren. Aus diesem Grund zeige ich Ihnen, wie ich eine generische Repository
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);
}
Aber definieren manchmal, müssen Sie nicht alle Methoden, die von generischen Repository-Schnittstelle definiert werden soll. Lösung: Erstellen Sie eine AbstractRepository-Klasse, die ein Dummy-Repository implementiert.Spring Framework zum Beispiel schwer, diese Art von Muster verwenden Schnittstelle >> 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.");
}
}
So Ihre GiftCardRepository werden kann neu geschrieben als (Siehe erstreckt statt Geräte) und überschreibt nur, was Sie wirklich wollen
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 {}
}
Jetzt externalisieren wir unsere benannte Abfrage in einem mehrzeiligen - und lesbar und wartbar - xML-Datei
// 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>
Also, wenn Sie Sie Giftcard mit dem Käufer abrufen möchten, rufen Sie einfach
Repository<GiftCard, GiftCard, String> giftCardRepository;
List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITH_WITH_BUYER);
Und unsere Giftcard ohne keine Beziehung abzurufen, rufen Sie einfach
List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITHOUT_NO_RELATIONSHIP);
oder Verwendung import static
import static packageTo.GiftCardRepository.*;
Und
List<GiftCard> giftCardList = giftCardRepository.findAll(GIFT_CARDS_WITHOUT_NO_RELATIONSHIP);
Ich hoffe, es kann dir nützlich sein!
Sehr interessant ... das ist gutes Denkanstoß. Und es wirft eine Nebenfrage auf. Wie würde ich eine Abfrage durchführen, die keine anderen Objekte als die Ziel-GiftCard abruft? –
@Ben Benson Siehe GiftCardRepository (letzte Zeile), benannte Abfragedatei und zusätzlicher Code am unteren Rand. Wenn meine Antwort Ihre Anforderungen erfüllt, markieren Sie sie als akzeptiert. Vielen Dank –