W jaki sposób najwygodniej zamieniac encje na dto i na odwrót?
najlepiej w springu.
W jaki sposób najwygodniej zamieniac encje na dto i na odwrót?
najlepiej w springu.
możesz zrobić sobie jakiś inteface:
@FunctionalInterface
public interface BaseConverter<F,T> {
public T convert(F from);
default public Collection<T> convertAll(Collection<F> fElements){
Collection<T> convertedElement =
fElements.stream()
.map(element -> convert(element))
.collect(Collectors.toList());
return convertedElement;
}
}
i potem
@Component
public class DefaultUserConverter implements BaseConverter<User, UserDTO> {
@Override
public UserDTO convert(User from) {
UserDTO user = new UserDTO();
user.setUsername(from.getUsername());
user.setPassword(from.getPassword());
user.setEnabled(from.getEnabled());
return user;
}
}
Spring ogarnia wstrzykiwanie przez generyki więc zadziała
BaseConverter<Encja, DTO> costam
Dzięki, obadam.
Na razie uzywałem np. https://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Function.html
Znalazłem też cos takiego, co wyglada calkiem ciekawie, ale nie uzywalem : http://modelmapper.org/getting-started/
Biały Mleczarz napisał(a):
Dzięki, obadam.
Na razie uzywałem np. https://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/base/Function.html
Nic nie stoi na przeszkodzie żebyś tak zrobił - jednak, nazwa Function będzie trochę myląca, i mój converter ma zaimplementowanie konwertowanie po wielu elementach, i też jest funkcjonalny także możesz użyć z lambdy
hmm... no przyznaje, ze nazwa Funtion najszcżęśliwsza nie jest.
Co masz na mysli poprzez "konwertowanie po wielu elementach" ?
Bo jeśli DTO ma listę innych DTO to chyba tego nie ogarnie tylko trzeba pisac kolejny konwerter?
dzięki
A widzisz co robi moja domyślna metoda: **convertAll ** ?
Może i widzę, ale bez bicia przyznam się, że nie do końca rozumiem ;)
I w zasadzie lambd jeszcze nie zdązyłem poznac.
Biały Mleczarz napisał(a):
Może i widzę, ale bez bicia przyznam się, że nie do końca rozumiem ;)
I w zasadzie lambd jeszcze nie zdązyłem poznac.
Chodzi o to że od Javy 8 możesz w interface zaimplementować działającą metodą, możesz to porównać trochę do metod z klasy abstrakcyjnej. Teraz wystarczy Ci wiedzieć tyle że jeżeli zaimplementujesz w klasie A interface BaseConverter i zaimlementujesz metodę convert() to w convertAll używasz tej metody. i ta metoda convertAll, najprościej, jako parametr przyjmuje Collection czyli np: listę modeli, u mnie to będzie List<User> i idzie po każdym elemencie tej listy, i ten element czyli User convertuje na UserDTO (User -> UserDTO), potem zwraca Listę taki skonwertowanych elementów (List<User> -> List<UserDTO>)
A tak już totalnie abstrakcyjnie to przez konwertowanie po wielu elementach znaczy że mając obiekt
User user
to żeby skonwertować musisz odpalić: converter.convert(user)
Ale jak masz listę takich obiektów do skonwertowania to albo robisz to w for'ze:
```java
List<User> users;
for(User user: users){
converer.convert(user);
}
Albo możesz to zrobić jak cywilizowany człowiek:
converter.convertAll(users)
niezdecydowany napisał(a):
możesz zrobić sobie jakiś inteface:
@FunctionalInterface public interface BaseConverter<F,T> { public T convert(F from); default public Collection<T> convertAll(Collection<F> fElements){ Collection<T> convertedElement = fElements.stream() .map(element -> convert(element)) .collect(Collectors.toList()); return convertedElement; } }
i potem
@Component public class DefaultUserConverter implements BaseConverter<User, UserDTO> { @Override public UserDTO convert(User from) { UserDTO user = new UserDTO(); user.setUsername(from.getUsername()); user.setPassword(from.getPassword()); user.setEnabled(from.getEnabled()); return user; } }
Spring ogarnia wstrzykiwanie przez generyki więc zadziała
BaseConverter<Encja, DTO> costam
A jak najlepiej zrobić gdy potrzeba przekazać jakis dodatkowy argument, żeby coś na tej postawie coś w środku np. sformatować?
czyli coś w stylu. Ale jak lepiej to zrobić?
@Component
public class DefaultUserConverter {
public UserDTO convert(User from, String veryImportantParam) {
UserDTO user = new UserDTO();
user.setUsername(from.getUsername() + veryImportantParam );
user.setPassword(from.getPassword());
user.setEnabled(from.getEnabled());
return user;
}
}
http://mapstruct.org/ - prost i przyjemne narzędzie :)
Ten Zły napisał(a):
http://mapstruct.org/ - prost i przyjemne narzędzie :)
mam dystans do takich narzędzi jednak i wolałbym ręcznie.
I tak się właśnie tworzy gettery i settery do zarypania. Pieknie.
Polecam jednak nie robić mapperów.
Jeśli już musisz JPA używać to da się to zrobić z immutable obiektami. Wtedy bez szkód można je przesłać między warstwami.
Po prostu zrób sobie różne obiekty na rózne use casy i bierz z bazy to co potrzebujesz -> select new.
Nawet mniej kodu niż z mapperami Ci wyjdzie, a będzie bezpieczniejsze.
Może cytat z bloga Vlada:
"DTO projections are better suited for fetching custom views, while entities should only be fetched when the business flow requires to modify them."
https://vladmihalcea.com/2016/06/28/14-high-performance-java-persistence-tips/
@Component public class DefaultUserConverter implements BaseConverter<User, UserDTO> { @Override public UserDTO convert(User from) { UserDTO user = new UserDTO(); user.setUsername(from.getUsername()); user.setPassword(from.getPassword()); user.setEnabled(from.getEnabled()); return user; } }
@Component public class DefaultUserConverter { public UserDTO convert(User from, String veryImportantParam) { UserDTO user = new UserDTO(); user.setUsername(from.getUsername() + veryImportantParam ); user.setPassword(from.getPassword()); user.setEnabled(from.getEnabled()); return user; } }
@jarekr000000 co bys polecał na ten drugi case z String veryImportantParam ?
final class UserFormatted {
final String notVeryImportantParam;
final UserData fromDb;
[... ciach ...]
String getUserNameFormatted() {
return fromDB.userName + notVeryImportantParam;
}
}