Spring & Hibernate Flashcards
Pytanie: Co to jest Spring Framework?
Odpowiedź: Spring to wszechstronny framework do tworzenia aplikacji w Javie. Umożliwia tworzenie aplikacji od pojedynczych modułów do kompleksowych rozwiązań korporacyjnych. Spring dostarcza infrastrukturę, dzięki której programiści mogą skupić się na tworzeniu aplikacji bez martwienia się o aspekty infrastrukturalne.
Pytanie: Jakie są główne moduły Spring Framework?
Odpowiedź: Główne moduły Springa to: Core Container, AOP (Aspect-Oriented Programming), Data Access/Integration, Web, Security, Messaging, Testing i inne.
Pytanie: Co to jest Inversion of Control (IoC) w Springu?
Odpowiedź: IoC to projektowy wzorzec, w którym obiekty nie tworzą zależności samodzielnie, ale zależności są wstrzykiwane przez zewnętrzny system. W Springu kontener IoC zarządza cyklem życia obiektów i wstrzykuje zależności.
Pytanie: Co to jest Hibernate?
Odpowiedź: Hibernate to framework ORM (Object-Relational Mapping), który umożliwia mapowanie obiektów Java na tabele w bazie danych i odwrotnie.
Pytanie: Co to jest sesja w Hibernate?
Odpowiedź: Sesja w Hibernate reprezentuje pojedynczą jednostkę rozmowy między aplikacją a bazą danych. Umożliwia tworzenie, odczyt, modyfikację i usuwanie obiektów.
Odpowiedź: Sesja w Hibernate to krótkotrwały obiekt, który działa jako most między aplikacją a bazą danych. Reprezentuje pojedynczą jednostkę pracy z bazą danych. Główne funkcje sesji to:
- Tworzenie, odczytywanie, aktualizowanie i usuwanie obiektów: Sesja umożliwia operacje CRUD na obiektach, które są mapowane na rekordy w bazie danych.
- Zarządzanie pierwszym poziomem pamięci podręcznej: Sesja posiada pierwszy poziom pamięci podręcznej, który przechowuje obiekty w trakcie jej życia.
- Zarządzanie transakcjami: Można rozpocząć i zakończyć transakcję bazodanową za pomocą sesji.
- Fabrykowanie zapytań: Umożliwia tworzenie zapytań, zarówno w języku HQL (Hibernate Query Language), jak i natywnych zapytań SQL, do interakcji z bazą danych.
- Zarządzanie stanem obiektów: Sesja śledzi stan obiektów i potrafi wykryć zmiany w obiektach, które są przez nią zarządzane.
- Łączenie i rozłączanie obiektów: Można łączyć obiekty z sesją lub je od niej odłączać.
Ważne jest, aby pamiętać, że sesja w Hibernate nie jest wątkowo bezpieczna, co oznacza, że każdy wątek powinien mieć swoją własną sesję. Po zakończeniu pracy z bazą danych sesję należy zamknąć, aby zwolnić zasoby.
Pytanie: Jakie są główne zalety korzystania z Hibernate?
Odpowiedź: Hibernate oferuje: abstrakcję od konkretnego dialektu bazy danych, cache drugiego poziomu, leniwe ładowanie, mapowanie obiektowo-relacyjne i wiele innych.
Pytanie: Jakie są różnice między @Autowired a @Resource w Springu?
Odpowiedź: @Autowired dokonuje wstrzyknięcia zależności przez typ, podczas gdy @Resource dokonuje wstrzyknięcia przez nazwę. @Autowired jest specyficzny dla Springa, podczas gdy @Resource jest częścią standardu Java.
Pytanie: Jakie są różnice między @Component, @Service, @Repository i @Controller w Springu?
Odpowiedź: Wszystkie te adnotacje są używane do wskazania, że klasa jest komponentem Springa. @Component to ogólna adnotacja. @Service wskazuje, że klasa jest używana jako serwis. @Repository wskazuje, że klasa jest używana jako repozytorium danych. @Controller wskazuje, że klasa jest kontrolerem w modelu MVC.
Pytanie: Jakie są różnice między @Component, @Service, @Repository i @Controller w Springu?
Odpowiedź: W Springu adnotacje @Component
, @Service
, @Repository
i @Controller
służą do wskazywania, że klasa jest komponentem zarządzanym przez kontener Springa (Spring Bean). Te adnotacje pozwalają na automatyczne wykrywanie komponentów za pomocą skanowania klasy. Oto różnice i specyficzne zastosowania każdej z tych adnotacji:
- @Component: Jest to ogólna adnotacja wskazująca, że klasa jest komponentem Springa. Może być używana w przypadku, gdy żadna z innych adnotacji nie pasuje dokładnie do przeznaczenia klasy.
-
@Service: Wskazuje, że klasa wykonuje usługę w warstwie usług (service layer) aplikacji. Jest to specjalizacja adnotacji
@Component
i nie dodaje dodatkowej funkcjonalności w porównaniu z@Component
, ale służy do wskazania celu klasy. -
@Repository: Używana w klasach, które dostarczają dostęp do danych, czyli w warstwie dostępu do danych (DAO layer). Dodatkowo, adnotacja
@Repository
zapewnia tłumaczenie wyjątków na wyjątki typu SpringDataAccessException
. - @Controller: Wskazuje, że klasa jest kontrolerem w modelu MVC i jest używana w warstwie prezentacji. W połączeniu z Spring MVC, klasy oznaczone tą adnotacją są komponentami, które mogą obsługiwać żądania HTTP.
Wszystkie te adnotacje są specjalizacjami adnotacji @Component
i służą głównie celom semantycznym oraz dokumentacyjnym, aby wskazać przeznaczenie klasy w architekturze aplikacji. Jednakże, jak w przypadku @Repository
, niektóre z tych adnotacji mogą dostarczać dodatkowej funkcjonalności.
Pytanie: Jakie są strategie dziedziczenia w Hibernate?
Odpowiedź: Hibernate oferuje trzy strategie dziedziczenia: pojedyncza tabela, tabela po tabeli i połączona.
W Hibernate istnieją trzy główne strategie dziedziczenia, które pozwalają na mapowanie hierarchii klas Java na schemat bazy danych. Oto one:
-
Strategia jednej tabeli (Single Table Strategy):
- Wszystkie klasy w hierarchii dziedziczenia są mapowane na jedną tabelę w bazie danych.
- Tabela ta zawiera kolumny dla wszystkich atrybutów wszystkich klas w hierarchii.
- Wprowadzana jest dodatkowa kolumna dyskryminatora (często nazywana “DTYPE” w Hibernate), która wskazuje, do której klasy w hierarchii należy dany rekord.
- Rekordy dla podklas mają wartości
null
w kolumnach, które nie są dla nich odpowiednie.
-
Strategia tabeli konkretnej klasy (Table Per Concrete Class Strategy):
- Każda klasa w hierarchii dziedziczenia jest mapowana na własną, oddzielną tabelę.
- Tabela dla konkretnej klasy zawiera kolumny dla wszystkich atrybutów tej klasy, włącznie z atrybutami klasy nadrzędnej.
- Nie ma dodatkowej kolumny dyskryminatora, ponieważ każda tabela reprezentuje konkretną klasę.
- W tej strategii nie jest możliwe ustawienie klucza głównego jako klucza obcego w innych tabelach, ponieważ nie ma gwarancji unikalności między tabelami.
-
Strategia jednej tabeli na klasę (Table Per Class Strategy):
- Każda klasa w hierarchii dziedziczenia ma swoją własną tabelę.
- Tabela dla podklasy zawiera tylko kolumny dla atrybutów zdefiniowanych w tej podklasie, nie dla atrybutów klasy nadrzędnej.
- Klucze główne są dzielone między tabelami, co oznacza, że rekord w tabeli podklasy ma ten sam klucz główny co odpowiadający mu rekord w tabeli klasy nadrzędnej.
- Ta strategia jest często uważana za kompromis między dwiema wcześniejszymi strategiami.
Wybór odpowiedniej strategii dziedziczenia zależy od konkretnych wymagań aplikacji i modelu danych. Każda strategia ma swoje zalety i wady, dlatego ważne jest zrozumienie ich charakterystyki przed podjęciem decyzji.
Pytanie: Co to jest AOP w Springu?
Odpowiedź: AOP (Aspect-Oriented Programming) to paradygmat programowania, który koncentruje się na aspektach aplikacji, takich jak logowanie, bezpieczeństwo itp., które są rozproszone po całej aplikacji.
AOP, czyli Aspect-Oriented Programming (Programowanie zorientowane aspektowo), to paradygmat programowania, który koncentruje się na “przekrojowych” (ang. “cross-cutting”) troskach w aplikacji. Przekrojowe troski to te aspekty programu, które wpływają na wiele modułów i są często rozproszone w całym kodzie, takie jak logowanie, zarządzanie transakcjami, bezpieczeństwo itp.
AOP w Springu oferuje sposób na modularizację przekrojowych trosk poprzez oddzielenie logiki biznesowej od logiki przekrojowej. Oto kilka kluczowych koncepcji związanych z AOP w Springu:
- Aspect (Aspekt): Moduł, który definiuje przekrojową troskę. Aspekt jest odpowiedzialny za wstrzykiwanie określonego zachowania w określone miejsca w kodzie.
- Join Point (Punkt przecięcia): Miejsce w kodzie, gdzie aspekt może być wstrzyknięty. W Spring AOP, join point zawsze reprezentuje wywołanie metody.
- Advice (Porada): Działanie podejmowane przez aspekt w danym join point. Istnieje kilka typów porad, takich jak “before” (przed), “after” (po), “after-returning” (po zwróceniu wartości), “after-throwing” (po zgłoszeniu wyjątku) i “around” (wokół, gdzie porada otacza wywołanie metody).
- Pointcut (Wyrażenie przecięcia): Wyrażenie, które określa, dla których join points ma zostać zastosowana dana porada. Pozwala to na precyzyjne określenie, gdzie w kodzie ma zostać wstrzyknięty aspekt.
- Target (Cel): Obiekt, którego metoda jest wywoływana i na którym działają aspekty.
- Proxy (Pełnomocnik): Obiekt stworzony przez Spring AOP, który “opakowuje” docelowy obiekt i dodaje do niego dodatkowe zachowanie (aspekty).
- Weaving (Tkanko): Proces łączenia aspektów z innym kodem aplikacji do utworzenia utkanej wersji kodu. W Spring AOP, tkanko może odbywać się w czasie kompilacji, ładowania klasy lub w czasie wykonywania.
AOP w Springu jest realizowane głównie za pomocą proxy opartych na interfejsach lub klasach, co oznacza, że tworzone są dynamiczne pełnomocniki, które “opakowują” docelowe obiekty i wstrzykują aspekty w odpowiednich miejscach.
Pytanie: Jakie są główne zalety korzystania z Spring Boot?
Odpowiedź: Spring Boot oferuje: automatyczną konfigurację, wbudowane narzędzia do monitorowania i zarządzania aplikacją, szeroką gamę wstępnie skonfigurowanych komponentów i wiele innych.
Spring Boot to projekt z ekosystemu Spring, który ma na celu ułatwienie tworzenia aplikacji opartych na Springu. Głównym celem Spring Boot jest minimalizacja konfiguracji wymaganej do uruchomienia aplikacji Springowej. Oto kilka kluczowych zalet Spring Boot:
- Szybkie i łatwe rozpoczęcie pracy: Spring Boot oferuje szereg “starterów”, które są zestawami zależności dobrze do siebie pasujących, co pozwala szybko zacząć pracę z konkretnymi modułami (np. Spring Data, Spring Security).
- Konwencja nad konfiguracją: Spring Boot dostarcza domyślne konfiguracje, które są zazwyczaj odpowiednie dla wielu aplikacji, zmniejszając potrzebę ręcznej konfiguracji.
- Wbudowany serwer: Spring Boot zawiera wbudowane instancje serwerów aplikacji (takich jak Tomcat, Jetty, czy Undertow), co pozwala na uruchomienie aplikacji bezpośrednio z IDE bez konieczności osobnego wdrażania na serwer aplikacji.
- Mikrousługi i chmura: Spring Boot jest dobrze przystosowany do budowy mikrousług i wspiera różne wzorce i narzędzia chmurowe, co ułatwia tworzenie skalowalnych i elastycznych aplikacji.
- Zarządzanie zależnościami: Spring Boot zarządza wersjami zależności, co ułatwia zarządzanie zależnościami i ich kompatybilnością.
- Aktuatory i monitoring: Spring Boot Actuator dostarcza gotowe punkty końcowe do monitorowania i zarządzania aplikacją w czasie działania, co jest ważne w produkcji.
- Łatwe testowanie: Spring Boot ułatwia testowanie aplikacji poprzez dostarczanie narzędzi do testowania, w tym wsparcie dla testów integracyjnych.
- Rozszerzalność: Można łatwo rozszerzać konfigurację domyślną i dostosowywać aplikację do swoich potrzeb.
Spring Boot jest szczególnie korzystny dla początkujących programistów Spring, ponieważ znacznie upraszcza proces konfiguracji i wdrożenia aplikacji, ale jest również ceniony przez doświadczonych deweloperów za oszczędność czasu i usprawnienie procesu tworzenia aplikacji.
Pytanie: Jak Hibernate radzi sobie z problemem N+1?
Odpowiedź: Hibernate oferuje strategie ładowania, takie jak leniwe i chciwe ładowanie, oraz możliwość korzystania z HQL lub kryteriów do optymalizacji zapytań.
Pytanie: Jak Hibernate radzi sobie z problemem N+1?
Odpowiedź: Problem N+1 występuje, gdy podczas ładowania encji i jej powiązań z innych encjami, system wykonuje jedno zapytanie, aby pobrać główną encję, a następnie dodatkowe zapytania dla każdej powiązanej encji. W efekcie, dla N powiązanych encji, wykonuje się N+1 zapytań do bazy danych. Hibernate oferuje kilka sposobów radzenia sobie z tym problemem:
-
Eager Fetching (Ładowanie zachłanne): Można skonfigurować powiązania między encjami tak, aby były ładowane “zachłannie” (
FetchType.EAGER
). Oznacza to, że powiązane encje są ładowane od razu w momencie ładowania głównej encji. W praktyce często używa się tego w połączeniu z JOIN FETCH w HQL lub JPQL, aby zmusić Hibernate do wykonania złączenia i pobrania wszystkich potrzebnych danych w jednym zapytaniu. - Batch Fetching (Ładowanie wsadowe): Można skonfigurować Hibernate, aby ładował powiązane encje w paczkach (batchach) określonego rozmiaru. Na przykład, jeśli rozmiar paczki wynosi 10, a mamy 30 powiązanych encji, Hibernate wykona 3 zapytania, każde dla 10 encji.
- Second Level Cache (Drugi poziom pamięci podręcznej): Hibernate oferuje drugi poziom pamięci podręcznej, który może być używany do przechowywania często używanych encji. Jeśli encje są już w pamięci podręcznej, nie ma potrzeby wykonywania dodatkowych zapytań do bazy danych.
- Subselect Fetching (Ładowanie podzapytaniem): Dla kolekcji, można skonfigurować ładowanie za pomocą podzapytania. Gdy główna encja jest ładowana, Hibernate generuje podzapytanie, które ładuje powiązane encje dla wszystkich głównych encji w bieżącej sesji.
- Named Entity Graphs: W JPA 2.1 wprowadzono koncepcję Named Entity Graphs, która pozwala na precyzyjne określenie, które atrybuty encji powinny być ładowane (zarówno zachłannie, jak i leniwie) dla danego zapytania.
Aby skutecznie radzić sobie z problemem N+1 w Hibernate, ważne jest zrozumienie charakterystyki danych i wzorców dostępu do nich w aplikacji, a następnie odpowiednie dostosowanie strategii ładowania. Monitoring wydajności i analiza generowanych zapytań SQL są kluczowe w identyfikowaniu i rozwiązywaniu problemów związanych z tym zagadnieniem.
Pytanie: Jak w Springu można zabezpieczyć aplikację?
Odpowiedź: Można użyć Spring Security, który oferuje autentykację, autoryzację, ochronę przed atakami CSRF, integrację z OAuth2 i wiele innych funkcji bezpieczeństwa.
W Springu do zabezpieczania aplikacji najczęściej używa się modułu Spring Security. Jest to rozbudowany framework, który oferuje szeroki zakres funkcji związanych z uwierzytelnianiem, autoryzacją oraz ochroną przed różnymi rodzajami ataków. Oto kilka kroków i funkcji, które można wykorzystać do zabezpieczenia aplikacji w Springu:
-
Dodanie zależności Spring Security:
Aby rozpocząć pracę z Spring Security, należy dodać odpowiednie zależności do projektu. -
Konfiguracja bezpieczeństwa:
- Można skonfigurować bezpieczeństwo zarówno za pomocą konfiguracji XML, jak i konfiguracji opartej na Javie.
- W konfiguracji określa się, które ścieżki są zabezpieczone, jakie mają wymagania dotyczące uwierzytelniania i autoryzacji, jakie źródło danych jest używane do uwierzytelniania użytkowników itp.
-
Uwierzytelnianie:
- Spring Security oferuje wiele mechanizmów uwierzytelniania, takich jak uwierzytelnianie oparte na formularzu, uwierzytelnianie HTTP Basic, uwierzytelnianie oparte na tokenach JWT itp.
- Można zdefiniować własne serwisy uwierzytelniania, które łączą się z bazą danych, serwisem LDAP, OAuth2 lub innym źródłem danych.
-
Autoryzacja:
- Po uwierzytelnieniu użytkownika można określić, jakie uprawnienia (role) ma przypisane i na tej podstawie kontrolować dostęp do różnych części aplikacji.
- Za pomocą adnotacji takich jak
@PreAuthorize
można określić, które metody mogą być wywoływane przez użytkowników z określonymi uprawnieniami.
-
Ochrona przed atakami:
- Spring Security oferuje ochronę przed wieloma powszechnymi atakami, takimi jak CSRF (Cross-Site Request Forgery), XSS (Cross-Site Scripting) czy Session Fixation.
- Domyślnie włączona jest ochrona przed atakami CSRF w aplikacjach opartych na formularzach.
-
Integracja z HTTPS:
- Można skonfigurować Spring Security, aby wymuszać komunikację za pomocą protokołu HTTPS dla określonych ścieżek lub dla całej aplikacji.
-
Wylogowywanie:
- Spring Security oferuje mechanizm wylogowywania, który pozwala na bezpieczne zakończenie sesji użytkownika.
-
Remember-Me:
- Funkcja “Remember-Me” pozwala na utrzymanie sesji użytkownika nawet po zamknięciu przeglądarki, dzięki specjalnym ciasteczkom.
-
Integracja z OAuth2 i JWT:
- Dla aplikacji, które wymagają uwierzytelniania opartego na tokenach lub integracji z zewnętrznymi dostawcami uwierzytelniania, Spring Security oferuje wsparcie dla OAuth2 i JWT.
Aby skutecznie zabezpieczyć aplikację w Springu, ważne jest zrozumienie różnych aspektów bezpieczeństwa i odpowiednie skonfigurowanie Spring Security zgodnie z wymaganiami aplikacji. Regularne aktualizacje i monitorowanie są kluczowe, aby zapewnić, że aplikacja jest chroniona przed nowymi zagrożeniami i podatnościami.
Pytanie: Jakie są różnice między @Bean a @Component w Springu?
Odpowiedź: @Bean jest używane w konfiguracji Java do deklarowania komponentu, podczas gdy @Component jest używane bezpośrednio na klasach, aby wskazać, że są one komponentami Springa.
Pytanie: Jakie są różnice między save() a persist() w Hibernate?
Odpowiedź: Metoda save() zwraca identyfikator po zapisaniu obiektu, podczas gdy persist() nie zwraca niczego. persist() również gwarantuje, że obiekt zostanie zarządzany przez kontekst trwałości od razu po wywołaniu metody.