Przepisywanie wartości między obiektami

0

Witam,
poszukuje jakieś biblioteki, wzorca... do rozwiązania takiego problemu -> Załóżmy sobie, że mamy jakąś klasę reprezentującą encje w bazie i klasę formularza którą wyrzucamy na widok. Klasy zazwyczaj w takich przypadkach są takie same lub różnią się paroma polami. Pytanie jak to szybko i łatwo pozamieniać w jedną i drugą stronę. Poniżej prosty i mały przykład.

Załóżmy że w bazie mam tabelkę Person, więc tworzymy sobie taką klasę.

 
class Person{
	private String firstName;
	private String lastName;
	private boolean adult;
	
	//getters and setters
}

Formularz na naszej stronie będzie reprezentowała klasa PersonForm.

clas PersonForm{
	private String firstName;
	private String lastName;
	private int age;
	
	//getters and setters
}

Jeśli użytkownik wyślę ten formularz to będziemy chcieli to zapisać to wszystko.

 
person.setFirstName(personForm.getFirstName());
...
if(personForm.getAge()>=18){
	person.setAdult(true);
}else{
	person.setAdult(false);
}
...

Pytanie czy da się to jakoś w prosty i szybki sposób zrobić? Inaczej niż pisać person.set...(personForm.get...()); gdzie czasami tych pól jest dość sporo.

0

Zobacz na http://dozer.sourceforge.net/ Do zamiany inta na boola będziesz musiał napisać sobie tylko konwerter.

ew. możesz jeszcze spojrzeć na https://code.google.com/p/orika/ bo widzę, że Dozer coś od dawna nie był wydawany :/

0

W formularzu stwórz pole Person i potem tylko zwracaj obiekt tego pola do przypisania.

0

Dzięki za naprowadzenie na właściwą drogę. Jeszcze dość ciekawą opcją wydaje się ModeMapper http://modelmapper.org/

0

Jeszcze ciekawszą opcją może być użycie frameworka(np. Spring) :P. Tam ktoś mądry zrobił większość rzeczy tego typu za Ciebie ;)

0

Ooo jak coś takiego jest w Springu to idealnie. Możesz jakoś nakierować, gdzie tego szukać w Springu?

0

@Kandif tragiczny pomysł który często skutkuje bardzo poważnymi i trudnymi do wyśledzenia błędami. Bo może się nagle okazać że będziesz sobie szykował obiekty żeby wysłać je do widoku i na przykład postanowisz wyrzucic kilka z nich z kolekcji a potem nagle sie okaże że sesja z bazą danych nadal była otwarta (bo transakcja na poziomie serwisu) i ci znikną te encje z bazy a ty nie będziesz wiedział co sie stało.
@gaUa69 Spring nie ma czegoś takiego, chyba że w 4 dodali, ale wątpię.

0

@Shalom pewnie masz racje :). Programuje w php i Symfony 2, tam są obiektowe formularze, które pod spodem działają na wskazanym modelu, co by rozwiązało jego problem. Pomyślałem, że w Javie webowej rozwiązali to podobnie ;).

0

Stwórz sobie np. taki interfejs:

public interface Mapper<I,O>
{
    public O map(I input);
}

i dla każdej z "par" obiektów stwórz konkretną implementację

0

Przetestowałem sobie na szybko ModelMapper i Orika. Rozwiązanie jest fajny jak chcemy kopiować pola o tych samych nazwach między obiektami. Ogólnie chciałem przyspieszyć pracę nad pewnymi elementami, ale czy to przyspiesza pracę? W powyższym przykładzie szybciej byłoby zrobić person.set...(personForm.get...()); Pytanie teraz kiedy i w jakich sytuacjach to stosować i czy się to opłaca? Poniżej przedstawia to co udało mi się zrobić.

ModelMapper

 
ModelMapper modelMapper = new ModelMapper();
		
		final Converter<Integer, Boolean> conv = new AbstractConverter<Integer, Boolean>() {
			@Override
			protected Boolean convert(Integer source) {
				if(source>=18){
					return true;
				}else{
					return false;
				}
			}
		};
		
		PropertyMap<PersonForm, Person> orderMap = new PropertyMap<PersonForm, Person>() {
			@Override
			protected void configure() {
				using(conv).map(source.getAge()).setAdult(false);
			}
		};
		
		modelMapper.addMappings(orderMap);
		Person personMM = modelMapper.map(personForm, Person.class);
		
		System.out.println("ModelMapper");
		System.out.println(personMM.getFirstName());
		System.out.println(personMM.getLastName());
		System.out.println(personMM.isAdult());

Orika

MapperFactory factory = new DefaultMapperFactory.Builder().build();
		ClassMapBuilder<PersonForm, Person> builder = factory.classMap(PersonForm.class, Person.class);
		
		builder.customize(new CustomMapper<PersonForm, Person>() {
			@Override
			public void mapAtoB(PersonForm a, Person b, MappingContext context) {
				if(a.getAge()>=18){
					b.setAdult(true);
				}else{
					b.setAdult(false);
				}
				
			}
		});
		
		factory.registerClassMap(builder.byDefault().toClassMap());
		MapperFacade mapper = factory.getMapperFacade();
		Person p = mapper.map(personForm, Person.class);
		
		System.out.println("ORIKA");
		System.out.println(p.getFirstName());
		System.out.println(p.getLastName());
		System.out.println(p.isAdult());

1 użytkowników online, w tym zalogowanych: 0, gości: 1