Jestem nowy na wiosnę i jestem bardzo podekscytowany tym, co oferuje!Najlepsza praktyka dla rzeczywistych DAO używających @Cacheable adnotacje
W tej chwili próbuję zmodernizować kilka DAO w moim istniejącym projekcie. W szczególności chcę zamienić mój stary zwykły kod JDBC na obsługę Spring Jdbc i wprowadzić przejrzyste buforowanie Spring.
Pierwsze pytanie: czy mam rację, że warstwa DAO jest właściwym miejscem, aby dodać
@Cacheable
adnotacje? Czy robisz to w warstwie biznesowej?Mogę śledzić wszystkie proste przykłady, które można znaleźć w Internecie. Jednak, gdy chodzi o więcej kodu prawdziwy świat, mam utknąć:
Konkretnie mam kilku metod, które zwracają instancji mojego modelu Publisher
. W moich ręcznych implementacjach pamięci podręcznej zawsze upewniłem się, że tylko jedna instancja jest buforowana i pobierana dla różnych metod. Jednak przy użyciu @Cacheable
i próbę enkapsulacji pamięci podręcznej w ramach DAO, mam problem, że adnotacja nie działa dla lokalnych wywołań metod (z powodu proxy).
Oto mój przykładowy kod:
@Cacheable("publisherCache")
public Publisher getPublisher(int publisherId)
{
String sql = "SELECT * FROM publisher LEFT JOIN publisherContacts USING (publisherId) WHERE publisherId=? ORDER BY publisherContactId ASC";
return getJdbcTemplate().query(sql, publisherResultSetExtractor, publisherId);
}
public List<Publisher> findVisiblePublishers()
{
List<Publisher> publishers = new LinkedList<Publisher>();
for (int publisherId : findVisiblePublisherIds())
{
publishers.add(getPublisher(publisherId));
}
return publishers;
}
@Cacheable(value = "publisherCache", key = "'list'")
private List<Integer> findVisiblePublisherIds()
{
String sql = "SELECT publisherId FROM publisher WHERE isVisible='yes' ORDER BY imprintName";
return getJdbcTemplate().queryForList(sql, Integer.class);
}
public Publisher findNearestPublisher(String appx)
{
appx = "%" + appx + "%";
String sql = "SELECT publisherId FROM publisher WHERE publisherName LIKE ? OR imprintName LIKE ? ORDER BY imprintName DESC LIMIT 1";
Integer publisherId = getJdbcTemplate().queryForObject(sql, Integer.class, appx, appx);
if (publisherId == null)
return null;
else
return getPublisher(publisherId);
}
To był mój pomysł, który jak powiedział, nie działa.
Jedyne alternatywy widzę teraz to:
a) buforować jedynie metodę getPublisher(publisherId)
i zdefiniować wszystkie inne metody, które zwracają Publisher
s, aby powrócić int
s (publisherIds) lub jego list. To nie jest naturalne z punktu widzenia API. Jako logikę usług lub biznesu oczekiwałbym, że otrzymam instancje od DAO, a nie tylko od identyfikatorów.
b) Dodaj @Cacheable
do wszystkich metod, duplikuj pamięć podręczną i wykorzystuj więcej pamięci niż potrzeba (załóżmy, że jest wielu wydawców i są to ciężkie obiekty).
Jaka jest najlepsza praktyka związana z tym musi być dość powszechny problem z? Dzięki za wszelkie spostrzeżenia.
Lepiej umieścić dwa pytania w dwóch pytaniach SO. – Raedwald
Dlaczego nie buforować wyniku metody 'findVisiblePublishers'? Tak, po uruchomieniu po raz pierwszy uruchomi dwa zapytania DB, ale to wszystko. Myślę, że to dobry cel do buforowania – Mikhail
Dzięki Michaił. Ponieważ spowoduje buforowanie obiektów wydawcy dla każdej listy wydawców, które zwrócę (i pamięć podręczną). Przedstawione powyżej podejście za pomocą getPublisher (id) nie działa. Kiedy wywołujesz getPublisher (id) z tej samej klasy, pamięć podręczna nie jest pytana, ale żądanie DB jest wykonywane za każdym razem. Oznacza to, że mam dwie instancje tego samego wydawcy w pamięci podręcznej, raz na liście i raz jako pojedynczy element. Kiedy będę miał bardziej podobne metody, sprawy się pogorszą. – marc82ch