
Implementacja bazy danych przy pomocy Spring Boot
Po co nam właściwie mongo?
- Znacznie bardziej wydajna od relacyjnych baz danych
- Znacznie łatwiejsza obsługa zapytań
- Przyzwoita liczba narzędzi w porównaniu do RDBMS
- Nie potrzebuje wydajnego serwera do funkcjonowania
- Znaczne możliwości skalowania zasobów i dobra kooperacja wielu serwerów współpracującyh ze sobą


Wady?
- Drastycznie zmniejszone bezpieczeństwo (transakcje mocno ograniczone)
- Nie ma żadnego stałego schematu bazy danych
- Łamie zasady ACID
- Baza danych jest uzależniona od aplikacji, która z nią współpracuje
- Bardzo łatwo zepsuć spójność bazy danych
W naszym projekcie wykorzystaliśmy Framework Spring, który zawiera dodatkowe biblioteki do obsługi bazy danych Mongo
Projekt bazy danych




{
"_id": "1",
"_class": "pl.edu.amu.wmi.wtf.fbs.be.entity.User",
"nickname": "Cukiernik",
"firstName": "Karol",
"lastName": "W",
"country": "Poland",
"address": "ul. Franciszkańska 44 Kraków",
"zipcode": "62-063",
"email": "karolw@gmail.com",
"userstatus": "ONLINE",
"style": 2,
"age": 13,
"aboutMe": "sympatyk cukiernictwa",
"registrationDate": {
"$date": "2015-11-16T22:41:38.068Z"
},
"Rates": [
{
"_id": "1",
"rating": "POSITIVE",
"userratedId": {
"$ref": "user",
"$id": "0"
},
"postratedId": {
"$ref": "Post",
"$id": "1"
}
}
],
"rateCounter": 0,
"userComments": [
{
"$ref": "Comment",
"$id": "1"
}
]
}Dokumenty mongoDB zapisywane są w formacie BSON i moją podobną budowę jak pliki JSON, dzięki czemu są bardzo czytelne dla człowieka. Formatu BSON został zaprojektowany, aby dostarczyć dodatkowe typy danych, zwiększyć efektywność kodowania i szybkość przeszukiwania.
Powyższy efekt uzyskaliśmy dzięki implementacji szkieletu bazy danych w Spring oraz obsłudze i wpakowaniu danych z aplikacji do bazy.
Nie każdy dokument będzie posiadać tą samą ilość pól. Jedynym obowiązkowym polem jest _id
W Mongo nie ma jako takich zdefiniowanych relacji. Wykorzystujemy "wbudowywanie" dokumentu lub referencje dostarczane przez zewnętrzną aplikację.
Szkielet przykładowego dokumentu
@Document(collection = "User")
public class User extends ContentsRateOrganizer implements Documents{
public enum userstatusStates {
HIDDEN, BANNED, DELETED, ONLINE, OFFLINE;
}
@Id
private String id;
@Indexed(unique = true)
private String nickname;
private String firstName;
private String lastName;
private String country;
private String address;
private String zipcode;
@Indexed(unique = true)
private String email;
private userstatusStates userstatus;
private int style;
private int age;
private AccessData useraccountData;
@DBRef
private List<Post> userPosts;
@DBRef
private List<Comment> userComments;
private List<Opinion> userOpinions;
private List<Share> userShares;
private List<Blog> userBlogs;
private String aboutMe;
@DateTimeFormat(iso = ISO.DATE_TIME)
private Date registrationDate;
} W samym szkielecie decydujemy o zastosowaniu konkretnej relacji do pola w bazie danych. Mongo różni się od innych baz w postrzeganiu relacji 1:N - tutaj mamy 1:kilku (zazwyczaj wbudowanie), 1:kilkuset (zazwyczaj hybrydowa referencja), 1:kilku milionów (sama referencja).
Jeśli nie zdefiniujemy lub wstawimy null do jakiegoś pola, to nie pojawi się ono w dokumencie w Mongo.
Taki szkielet wypełniamy danymi i przekazujemy innym obiektom do wysłania.
Resztę niepotrzebnych danych wypełniamy wartością null. Adnotacje służą wewnetrznej implementacji zasobów w Springu.
Przesyłanie danych do bazy

public static MongoOperations mongoOps;
static{
mongoOps=new MongoTemplate(
new Mongo(
new MongoURI("mongodb://altenfrost:altenfrost@ds053794.mongolab.com:53794/testing")),"testing");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
try{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new ClassPathResource("Spring-config.xml").getPath());
UserDao userdao=context.getBean(UserDao.class);
BlogDao blogdao=context.getBean(BlogDao.class);
CommentDao commentdao=context.getBean(CommentDao.class);
PostDao postdao=context.getBean(PostDao.class);
RateDao ratedao=context.getBean(RateDao.class);
TagDao tagdao=context.getBean(TagDao.class);
Documents document=new User();
User user=new User(null,0,String.valueOf(document.getNextId()),"Temp","Jan","Kowalski","Poland","ul. Grunwaldzka 44 Poznań","62-063","jankowalski@gmail.com",userstatusStates.ONLINE,1,28,null,null,null,null,null,null,null,"Przykładowy użytkownik",new Date());
User user2=new User(null,0,String.valueOf(document.getNextId()+1l),"Cukiernik","Karol","W","Poland","ul. Franciszkańska 44 Kraków","62-063","karolw@gmail.com",userstatusStates.ONLINE,2,13,null,null,null,null,null,null,null,"sympatyk cukiernictwa",new Date());
userdao.create(user);
userdao.create(user2);
document = new Tag();
Tag tag1=new Tag(String.valueOf(document.getNextId()+1l),"kuchnia",null);
List<Tag> taglists=new ArrayList<Tag>();
taglists.add(tag1);
tagdao.create(tag1);
Rate rate=new Rate();
document=rate;
rate=new Rate(String.valueOf(document.getNextId()+1l),user,null,Rated.POSITIVE);
List<Rate> ratelist=new ArrayList<>();
ratedao.create(rate);
Post post=new Post();
document=post;
post=new Post(ratelist,0,String.valueOf(document.getNextId()+1l),"Przykładowy wpis",new Date(),new Date(),user,null,taglists,null,"Test wpisy",null,contentstausStates.CREATED);
postdao.create(post);
Post post2=new Post(null,0,String.valueOf(document.getNextId()+2l),"Drugi przykładowy wpis",new Date(), new Date(),user,null,taglists,null,"Jakiś tam opis",null,contentstausStates.HIDDEN);
postdao.create(post2);
List<Post> postlist=new ArrayList<>();
postlist.add(post);
postlist.add(post2);
tag1.setRelatedPosts(postlist);
tagdao.update(tag1);
user.setUserPosts(postlist);
userdao.update(user);
rate.setPostratedId(post);
ratedao.update(rate);
ratelist.add(rate);
user2.setRates(ratelist);
userdao.update(user2);
Blog blog=new Blog();
document = blog;
blog=new Blog(String.valueOf(document.getNextId()+1l),"Blog o gotowaniu","Różne przepisy itp.","Blog kucharza","Super potrawy",new Date(),new Date(),postlist);
blogdao.create(blog);
List<Blog> bloglist=new ArrayList<Blog>();
bloglist.add(blog);
user.setUserBlogs(bloglist);
userdao.update(user);
Comment comment=new Comment();
document =comment;
comment=new Comment(null,0,String.valueOf(document.getNextId()+1l),post,new Date(),new Date(),null,"Super artykuł",null,contentstausStates.PUBLICATED);
commentdao.create(comment);
List<Comment> comments=new ArrayList<>();
comments.add(comment);
user2.setUserComments(comments);
userdao.update(user2);
}catch(Exception e){
e.printStackTrace();
}
}- Nawiązujemy połaczenie za pomocą zewnętrznego URI.
- Do obsługi metod konkretnych obiektów wykorzystano komponent DAO (dostarcza jednolity interfejs do komunikacji między aplikacją a źródłem danych i nieco zwieksza bezpieczeństwo).
- W celu ochrony spójnosci bazy danych Spring nie pozwala nam wprowadzić do bazy dokumentu, który zawieralby referencje do nieistniejacego dokumentu. Zatem na początku musimy wstawić dokument bez referencji, a później stopniowo wprowadzać update'y.
- Mongo łamie zasadę ACID - w przypadku nagłego wyłaczenia programu (np. w jednej z środkowych linijek) nic nie monitoruje trwałosci bazy danych i nic nas nie poinformuje o niedokończonym updacie danego dokumentu! (musimy założyć perfekcyjne działanie programu)
- Operacje przeprowadzane na Mongo są "ostateczne" - w przypadku aktualizacji jednego pola Mongo może nadpisać cały dokument. Bez zewnętrznej pomocy nie ma możliwości do archiwizacji danych.
Wnioski
- Mongo to bardzo szybka, ale i niebezpieczna baza danych
- Nadaje się do mniejszych projektów, nie należy jej stosować dużych aplikacjach biznesowych
- Świetnie sprawdza się jako magazyn dużej ilości szczegółowych i niezwiązanych ze sobą danych
- Relacje w bazie danych Mongo nie są pożądane i usuwamy je kosztem spójności i trwałości danych
- Najlepiej, jakby tylko kilku pojedyńczych użytkowników miało jakikolwiek dostęp do bazy danych
- Implementując rozwiazania mające na celu utrzymanie trwałosci i spójności narażamy się na wystepowanie najwiekszego problemu - duplikacji danych (np. wraz z dodaniem kolejnego użytkownika trzeba będzie aktualizować pozostałe kilka pól w innych kolekcjach)

- Aplikacja obsługująca bazę musi być zaopatrzona w prawie wszystkie elementy umożliwiające poprawne działanie bazy m.in. walidator i autentyfikacje danych
- Zapytania w Mongo są bardziej intuicyjne niż w SQL
TAS
By kko
TAS
Prezentacja na przedmiot Tworzenie aplikacji serwerowych
- 773