SMART IT
Toggle navigation
Niezalogowany
Logowanie
BLOG
Rejestracja
Kontakt
{{getUserDetails().email | limitToDots : 25}}
{{getUserDetails().email | limitToDots : 40}}
Twoje konto
Twoje konto
Wyloguj
BLOG
Rejestracja
Kontakt
Szybki Dostęp
Szybki Dostęp - Wprowadzenie
Maven - Instalacja
Maven - Pierwsze kroki
Maven - Cykle życia, fazy i cele
Maven - Asystent
Spring Boot - Aplikacja Webowa
Spring Boot - Projekt startowy
Spring Boot - Maven
Spring Boot - Konfiguracja
Git - Pierwsze kroki
Git - Tworzenie gałęzi (branchy)
Git - Aktualizacja gałęzi przed scaleniem (mergem)
Git - Konflikt w trakcie scalania (mergowania)
Java
Kursy PREMIUM
Kurs Java
Kurs Java - Wprowadzenie
Instalacja Javy
Narzędzia programistyczne (IDE)
Eclipse - Pierwszy projekt
IntelliJ - Instalacja i pierwsze kroki
Wprowadzenie do Javy
Hello JavAPPa
Typy proste
Operatory
Warunek If...Else
Instrukcja Switch
Pętla While
Pętla For
Kurs Java - Podstawy
Klasy i obiekty z życia wzięte
Klasy i programowanie obiektowe
Rodzaje metod w ramach obiektu
Metody statyczne
Tworzenie własnych obiektów
Typy obiektowe
Klasa String
Tablice obiektów i typów prostych
Klasy - Dziedziczenie
Przesłanianie metod
Przeciążanie metod
Modyfikatory dostępu
Klasy abstrakcyjne
Interfejsy
Inne metody w interfejsach
Interfejs jako typ danych
Polimorfizm
Enkapsulacja
Metoda
equals
Wyjątki w Javie
Pliki w Javie
Typy generyczne w Javie
Klasa z parametrem typu
Typ wyliczeniowy enum
Programow. obiektowe w Javie
Kolekcje - Wprowadzenie
Kolekcje - Listy
Kolekcje - Sety
Kolekcje - Mapy
Kolekcje w Javie
Java 8 do 17 i dalej - Spis treści
Wprowadzenie
Wyrażenia lambda - Starter
Wyrażenia lambda - Przykłady
Interfejs funkcyjny - Co to jest?
Przegląd interfejsów funkcyjnych
Wariacje interfejsów funkcyjnych
Składanie interfejsów funkcyjnych
Strumienie - Pierwsze kroki
Referencje do metod
Strumienie - Metody
peek
i
collect
Strumienie - Metody
map
i
flatMap
Strumienie - Metoda
reduce
Strumienie - Kolektory
Strumienie - Filtry
Klasa Optional
Data i czas w Javie 8
Operacje na datach w Javie 8
Nowe metody w kolekcjach
Nowe metody w mapach
Nowości w kodzie Java 9 do 11
Nowości w kodzie Java 12 do 14
Nowości w kodzie Java 15
Nowości w kodzie Java 16
Nowości w kodzie Java 17
Kurs Java 8 do 17 i dalej
Kurs Spring
Kurs Spring - Wprowadzenie
Projekty vs Moduły Springa
Stereotypy
Wstrzykiwanie zależności: DI & IoC
Wstrzykiwanie: Qualifier & Bean
Zakres Beana (Scope)
Wersje Springa
Spring Boot - Projekt startowy
Spring Boot - Maven
Spring Boot - Konfiguracja
Spring Boot Actuator
Spring Boot Actuator 2 / 3
Spring Framework - Podstawy
Spring Framework - Spring MVC
Spring MVC: Mapowanie requestów HTTP
Spring MVC: Mapowanie danych w requestach HTTP
Spring AOP - Podstawy
Spring AOP - AspectJ
Spring Data JPA - Podstawy
Spring Data JPA 2 / 3
Spring Data JPA: Zapytania Wbudowane (Built-in Queries)
Spring Data JPA: Zapytania Własne (Custom Queries)
Spring Data JPA: Zapytania Natywne (Native Queries)
Postman i Spring - Wysyłanie requestów
Kurs Angular
Kurs Angular/AngularJS - Wprowadzenie
Projekt startowy AngularJS
Moduł (Module)
Zakres (Scope)
Kontroler (Controller)
Dostawca stanu i dyrektywa ui-view
Serwis vs Fabryka (Service vs Factory)
Dostawca (Provider)
Wartość vs Stała (Value vs Constant)
Dyrektywy wbudowane
Dyrektywy własne
Dyrektywy własne - Atrybut dopasowujący wartość
@
Dyrektywy własne - Atrybuty dopasowujące własność
<
=
Dyrektywy własne - Atrybut funkcyjny
&
StartAPPa
Kurs Aplikacji Web
Jak to działa?
Starter REST
Kurs Aplikacji Web - Mega pakiet
Formularz Podstawowy
Formularz Zaawansowany
Tabela Podstawowa
Tabela Zaawansowana
Wykres Danych
Importer CSV
Importer XLS
Login & Reset
O Nas
Kim jesteśmy?
Nasze doświadczenie
Formularz kontaktowy
Hibernate - List vs Set w encjach
Strona główna
Hibernate - List vs Set w encjach
Post ten jest formą ćwiczenia, dlatego udostępniamy kod źródłowy w postaci pliku zip. Możecie go ściągnąć i własnoręcznie przetestować. Do pełnego zrozumienia przykładu wymagana jest wiedza ogólna z zakresu JPA (najlepiej implementacji dostarczanej przez Hibernate).
Załóżmy teraz, że w pewnej aplikacji webowej, napisanej z użyciem Spring Boot-a przechowujemy użytkowników uprawnionych do korzystania z tej aplikacji. Każdy z nich posiada przypisane elementy (itemy). Mamy więc encję
User
, w której przechowujemy encje
Items
. Relacja między encjami jest określona obustronnie jako
@ManyToMany
.
Napiszemy zapytanie
LEFT JOIN
, które operuje na encjach:
User
i
Item
. Za jego pomocą pokażemy, jak banalna różnica dotycząca użytego typu kolekcji w encji (
List
lub
Set
), może w efekcie doprowadzić ogromnej zmiany jaką jest zwrócenia całkowicie innego zestawu rekordów od spodziewanego.
List vs Set - Na czym polega różnica?
Tworzymy zapytanie w dwóch wersjach i w każdej z nich używamy kolekcje z tymi samymi danymi, ale stosując różne typy tych kolekcji:
List
(
usersList
) i
Set
(
usersSet
). Po uruchomieniu kodu zobaczymy, że w przypadku zastosowania interfejsu
Set
otrzymamy unikalnych użytkowników, podczas gdy stosując interfejs
List
otrzymamy użytkowników zduplikowanych! Różnica jest więc ogromna. Wynika to z natury Set-a (przechowuje tylko unikalne elementy), która znajduje przełożenie na inny rodzaj wykonywanego przez Hibernate'a złączenia.
Należy zatem dokładnie zwracać uwagę na typ danych w polach przechowujących kolekcje w naszych encjach. Błędne użycie interfejsu
List
lub
Set
może skutkować wystąpieniem trudnego do zdiagnozowania błędu, szczególnie w przypadku skomplikowanych zapytań. Poniżej prezentujemy najważniejsze klasy oraz udostępniamy zip-a z całym projektem Spring Boot.
Kod źródłowy
package com.javappa.postmodifying.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; @Entity @Table(name = "items") public class Item extends AbstractEntity
{ @Column(length = 255) private String name; @Column(length = 4000) private String description; @ManyToMany(cascade = { CascadeType.MERGE }) @JoinTable(name = "items_users", joinColumns = { @JoinColumn(name = "items_id") }, inverseJoinColumns = { @JoinColumn(name = "users_id") }) private Set
users = new HashSet
(); public Set
getUsers() { return users; } public void setUsers(Set
users) { this.users = users; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
package com.javappa.postmodifying.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; @Entity @Table(name = "users") public class User extends AbstractEntity
{ private String email; @ManyToMany(cascade = { CascadeType.MERGE }) @JoinTable(name = "items_users", joinColumns = { @JoinColumn(name = "users_id") }, inverseJoinColumns = { @JoinColumn(name = "items_id") }) private Set
items = new HashSet
(); public Set
getItems() { return items; } public void setItems(Set
items) { this.items = items; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
package com.javappa.postmodifying.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import com.javappa.postmodifying.domain.Item; public interface ItemRepository extends JpaRepository
{ @Transactional @Modifying @Query("DELETE FROM Item i WHERE i.name LIKE :prefix%") void deleteByPrefix(@Param("prefix") String prefix); }
package com.javappa.postentityset.domain; import java.io.Serializable; import java.util.Date; import java.util.Objects; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.springframework.data.domain.Persistable; @MappedSuperclass public abstract class AbstractEntity
implements Persistable
{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(unique = true, nullable = false) private ID id; @Column(name = "creation_date") @Temporal(TemporalType.TIMESTAMP) private Date creationDate; @Column(name = "modification_date") @Temporal(TemporalType.TIMESTAMP) private Date modificationDate; @Override public ID getId() { return id; } public void setId(ID id) { this.id = id; } @Override public boolean isNew() { return null == getId(); } @Override public int hashCode() { return Objects.hash(id); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof AbstractEntity)) { return false; } AbstractEntity> that = (AbstractEntity>) o; return Objects.equals(id, that.id); } @PrePersist protected void onCreate() { if (this.creationDate == null) { Date currentDate = new Date(); this.creationDate = currentDate; this.modificationDate = currentDate; } } @PreUpdate protected void onUpdate() { this.modificationDate = new Date(); } @Override public String toString() { return String.format("Entity of type %s with id: %s", this.getClass().getName(), getId()); } }
Autor:
Jarek Klimas
Data:
16 września 2018
Zapisz się do newslettera :
Zapisz się do newslettera :
Zapisz
Zapisz
Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy:
stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij
O nas
.
Starter
Jak to działa
Aplikacja
Obserwuj nas
Polityka Cookies
Regulamin
Licencja
Ochrona prywatności
Pozycjonowanie stron:
Grupa TENSE