Attualmente sto scrivendo un'applicazione web di medie dimensioni e mi trovo a fare questa domanda molte volte.
Per esempio, diciamo che ci sono utenti, che hanno file (uno-a-molti). Come dovrebbe l'interfaccia utente accedere ai dati? Un "estremo" sarebbe lasciare che il livello di servizio "solo" si occupi del caricamento pigro, cioè
public interface UserService {
public User createUser(String loginName, String password);
public Set<MediaFile> getFilesOfUser(User user);
}
o, d'altra parte, non restituiscono mai entità, solo i loro id
public interface UserService {
public long createUser(String loginName, String password);
public Set<Long> getFilesOfUser(long userId);
}
Ciò implica che il servizio avrebbe bisogno di metodi per interrogare (e impostare) anche tutti gli attributi "di base"
public interface UserService {
public long createUser(String loginName, String password);
public Set<Long> getFilesOfUser(long userId);
public String getNameOfUser(long userId);
public void setNameOfUser(long userId, String name);
}
Questo aggiunge un bel po 'di codice (e probabilmente un carico aggiuntivo al DB), ma protegge anche da StaleData- o LazyInitializationException.
Subquestion: come - se si utilizza il primo caso - l'aggiornamento, il recupero, ecc. devono essere implementati? Mi vengono in mente due metodi
In primo luogo, potrei provare ad aggiornare manualmente il riferimento originale (perché cose come i proxy di raccolta, la versione ecc. si aggiornano solo sull'oggetto restituito, non sul riferimento originale). Questo semplifica l'utilizzo di tali entità direttamente nell'interfaccia utente
public Set<MediaFile> getFilesOfUser(User user) {
Set<MediaFile> files = user.getFiles();
if(!Hibernate.isInitialized(files)) {
user.setFiles(userDao.findOne(user.getId()).getFiles()); // findOne to re-attach to the session
return ImmutableSet.<MediaFile> copyOf(files);
}
ma anche
public Set<MediaFile> getFilesOfUser(User user) {
return ImmutableSet.<MediaFile> copyOf(getUser(user.getId()).getFiles());
}
La maggiore differenza in queste viene mostrata quando si utilizza il controllo delle versioni. Nel primo caso, devo aggiornare manualmente la versione ecc. ( user.setVersion(attachedUser.getVersion())
) dopo ogni aggiornamento, nel secondo caso, una chiamata di aggiornamento deve recuperare l'entità ogni volta solo per impostare il valore:
public void update(User user) {
User attachedUser = getUser(user.getId());
attachedUser.setName(user.getName());
attachedUser.setPasswordHash(user.getPasswordHash());
// etc etc
userDao.save(attachedUser);
}
Questo non sembra molto efficiente / non intuitivo.
Qual è il modo corretto di andare?
Modifica
Solo un'altra idea riguardava il metodo del "solo ID di ritorno": i servizi potevano esporre un metodo pubblico "get