refactor: rename and delete some patterns (#2970)

This commit is contained in:
Ilkka Seppälä
2024-05-23 17:57:46 +03:00
committed by GitHub
parent 399970f8d1
commit 962e8898e0
94 changed files with 972 additions and 3619 deletions
@@ -0,0 +1,89 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.app;
import com.iluwatar.cqrs.commandes.CommandServiceImpl;
import com.iluwatar.cqrs.constants.AppConstants;
import com.iluwatar.cqrs.queries.QueryServiceImpl;
import com.iluwatar.cqrs.util.HibernateUtil;
import lombok.extern.slf4j.Slf4j;
/**
* CQRS : Command Query Responsibility Segregation. A pattern used to separate query services from
* commands or writes services. The pattern is very simple, but it has many consequences. For
* example, it can be used to tackle down a complex domain, or to use other architectures that were
* hard to implement with the classical way.
*
* <p>This implementation is an example of managing books and authors in a library. The persistence
* of books and authors is done according to the CQRS architecture. A command side that deals with a
* data model to persist(insert,update,delete) objects to a database. And a query side that uses
* native queries to get data from the database and return objects as DTOs (Data transfer Objects).
*/
@Slf4j
public class App {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
var commands = new CommandServiceImpl();
// Create Authors and Books using CommandService
commands.authorCreated(AppConstants.E_EVANS, "Eric Evans", "evans@email.com");
commands.authorCreated(AppConstants.J_BLOCH, "Joshua Bloch", "jBloch@email.com");
commands.authorCreated(AppConstants.M_FOWLER, "Martin Fowler", "mFowler@email.com");
commands.bookAddedToAuthor("Domain-Driven Design", 60.08, AppConstants.E_EVANS);
commands.bookAddedToAuthor("Effective Java", 40.54, AppConstants.J_BLOCH);
commands.bookAddedToAuthor("Java Puzzlers", 39.99, AppConstants.J_BLOCH);
commands.bookAddedToAuthor("Java Concurrency in Practice", 29.40, AppConstants.J_BLOCH);
commands.bookAddedToAuthor("Patterns of Enterprise"
+ " Application Architecture", 54.01, AppConstants.M_FOWLER);
commands.bookAddedToAuthor("Domain Specific Languages", 48.89, AppConstants.M_FOWLER);
commands.authorNameUpdated(AppConstants.E_EVANS, "Eric J. Evans");
var queries = new QueryServiceImpl();
// Query the database using QueryService
var nullAuthor = queries.getAuthorByUsername("username");
var evans = queries.getAuthorByUsername(AppConstants.E_EVANS);
var blochBooksCount = queries.getAuthorBooksCount(AppConstants.J_BLOCH);
var authorsCount = queries.getAuthorsCount();
var dddBook = queries.getBook("Domain-Driven Design");
var blochBooks = queries.getAuthorBooks(AppConstants.J_BLOCH);
LOGGER.info("Author username : {}", nullAuthor);
LOGGER.info("Author evans : {}", evans);
LOGGER.info("jBloch number of books : {}", blochBooksCount);
LOGGER.info("Number of authors : {}", authorsCount);
LOGGER.info("DDD book : {}", dddBook);
LOGGER.info("jBloch books : {}", blochBooks);
HibernateUtil.getSessionFactory().close();
}
}
@@ -0,0 +1,46 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.commandes;
/**
* This interface represents the commands of the CQRS pattern.
*/
public interface CommandService {
void authorCreated(String username, String name, String email);
void bookAddedToAuthor(String title, double price, String username);
void authorNameUpdated(String username, String name);
void authorUsernameUpdated(String oldUsername, String newUsername);
void authorEmailUpdated(String username, String email);
void bookTitleUpdated(String oldTitle, String newTitle);
void bookPriceUpdated(String title, double price);
}
@@ -0,0 +1,144 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.commandes;
import com.iluwatar.cqrs.domain.model.Author;
import com.iluwatar.cqrs.domain.model.Book;
import com.iluwatar.cqrs.util.HibernateUtil;
import org.hibernate.SessionFactory;
/**
* This class is an implementation of {@link CommandService} interface. It uses Hibernate as an api
* for persistence.
*/
public class CommandServiceImpl implements CommandService {
private final SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
private Author getAuthorByUsername(String username) {
Author author;
try (var session = sessionFactory.openSession()) {
var query = session.createQuery("from Author where username=:username");
query.setParameter("username", username);
author = (Author) query.uniqueResult();
}
if (author == null) {
HibernateUtil.getSessionFactory().close();
throw new NullPointerException("Author " + username + " doesn't exist!");
}
return author;
}
private Book getBookByTitle(String title) {
Book book;
try (var session = sessionFactory.openSession()) {
var query = session.createQuery("from Book where title=:title");
query.setParameter("title", title);
book = (Book) query.uniqueResult();
}
if (book == null) {
HibernateUtil.getSessionFactory().close();
throw new NullPointerException("Book " + title + " doesn't exist!");
}
return book;
}
@Override
public void authorCreated(String username, String name, String email) {
var author = new Author(username, name, email);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.save(author);
session.getTransaction().commit();
}
}
@Override
public void bookAddedToAuthor(String title, double price, String username) {
var author = getAuthorByUsername(username);
var book = new Book(title, price, author);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.save(book);
session.getTransaction().commit();
}
}
@Override
public void authorNameUpdated(String username, String name) {
var author = getAuthorByUsername(username);
author.setName(name);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.getTransaction().commit();
}
}
@Override
public void authorUsernameUpdated(String oldUsername, String newUsername) {
var author = getAuthorByUsername(oldUsername);
author.setUsername(newUsername);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.getTransaction().commit();
}
}
@Override
public void authorEmailUpdated(String username, String email) {
var author = getAuthorByUsername(username);
author.setEmail(email);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.getTransaction().commit();
}
}
@Override
public void bookTitleUpdated(String oldTitle, String newTitle) {
var book = getBookByTitle(oldTitle);
book.setTitle(newTitle);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(book);
session.getTransaction().commit();
}
}
@Override
public void bookPriceUpdated(String title, double price) {
var book = getBookByTitle(title);
book.setPrice(price);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(book);
session.getTransaction().commit();
}
}
}
@@ -0,0 +1,37 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.constants;
/**
* Class to define the constants.
*/
public class AppConstants {
public static final String E_EVANS = "eEvans";
public static final String J_BLOCH = "jBloch";
public static final String M_FOWLER = "mFowler";
public static final String USER_NAME = "username";
}
@@ -0,0 +1,66 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.domain.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* This is an Author entity. It is used by Hibernate for persistence.
*/
@ToString
@Getter
@Setter
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String username;
private String name;
private String email;
/**
* Constructor.
*
* @param username username of the author
* @param name name of the author
* @param email email of the author
*/
public Author(String username, String name, String email) {
this.username = username;
this.name = name;
this.email = email;
}
protected Author() {
}
}
@@ -0,0 +1,69 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.domain.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* This is a Book entity. It is used by Hibernate for persistence. Many books can be written by one
* {@link Author}
*/
@ToString
@Setter
@Getter
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String title;
private double price;
@ManyToOne
private Author author;
/**
* Constructor.
*
* @param title title of the book
* @param price price of the book
* @param author author of the book
*/
public Book(String title, double price, Author author) {
this.title = title;
this.price = price;
this.author = author;
}
protected Book() {
}
}
@@ -0,0 +1,47 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.dto;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* This is a DTO (Data Transfer Object) author, contains only useful information to be returned.
*/
@ToString
@EqualsAndHashCode
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Author {
private String name;
private String email;
private String username;
}
@@ -0,0 +1,46 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.dto;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* This is a DTO (Data Transfer Object) book, contains only useful information to be returned.
*/
@ToString
@EqualsAndHashCode
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private String title;
private double price;
}
@@ -0,0 +1,47 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.queries;
import com.iluwatar.cqrs.dto.Author;
import com.iluwatar.cqrs.dto.Book;
import java.math.BigInteger;
import java.util.List;
/**
* This interface represents the query methods of the CQRS pattern.
*/
public interface QueryService {
Author getAuthorByUsername(String username);
Book getBook(String title);
List<Book> getAuthorBooks(String username);
BigInteger getAuthorBooksCount(String username);
BigInteger getAuthorsCount();
}
@@ -0,0 +1,107 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.queries;
import com.iluwatar.cqrs.constants.AppConstants;
import com.iluwatar.cqrs.dto.Author;
import com.iluwatar.cqrs.dto.Book;
import com.iluwatar.cqrs.util.HibernateUtil;
import java.math.BigInteger;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
/**
* This class is an implementation of {@link QueryService}. It uses Hibernate native queries to
* return DTOs from the database.
*/
public class QueryServiceImpl implements QueryService {
private final SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
@Override
public Author getAuthorByUsername(String username) {
Author authorDto;
try (var session = sessionFactory.openSession()) {
Query<Author> sqlQuery = session.createQuery(
"select new com.iluwatar.cqrs.dto.Author(a.name, a.email, a.username)"
+ " from com.iluwatar.cqrs.domain.model.Author a where a.username=:username");
sqlQuery.setParameter(AppConstants.USER_NAME, username);
authorDto = sqlQuery.uniqueResult();
}
return authorDto;
}
@Override
public Book getBook(String title) {
Book bookDto;
try (var session = sessionFactory.openSession()) {
Query<Book> sqlQuery = session.createQuery(
"select new com.iluwatar.cqrs.dto.Book(b.title, b.price)"
+ " from com.iluwatar.cqrs.domain.model.Book b where b.title=:title");
sqlQuery.setParameter("title", title);
bookDto = sqlQuery.uniqueResult();
}
return bookDto;
}
@Override
public List<Book> getAuthorBooks(String username) {
List<Book> bookDtos;
try (var session = sessionFactory.openSession()) {
Query<Book> sqlQuery = session.createQuery(
"select new com.iluwatar.cqrs.dto.Book(b.title, b.price)"
+ " from com.iluwatar.cqrs.domain.model.Author a, com.iluwatar.cqrs.domain.model.Book b "
+ "where b.author.id = a.id and a.username=:username");
sqlQuery.setParameter(AppConstants.USER_NAME, username);
bookDtos = sqlQuery.list();
}
return bookDtos;
}
@Override
public BigInteger getAuthorBooksCount(String username) {
BigInteger bookcount;
try (var session = sessionFactory.openSession()) {
var sqlQuery = session.createNativeQuery(
"SELECT count(b.title)" + " FROM Book b, Author a"
+ " where b.author_id = a.id and a.username=:username");
sqlQuery.setParameter(AppConstants.USER_NAME, username);
bookcount = (BigInteger) sqlQuery.uniqueResult();
}
return bookcount;
}
@Override
public BigInteger getAuthorsCount() {
BigInteger authorcount;
try (var session = sessionFactory.openSession()) {
var sqlQuery = session.createNativeQuery("SELECT count(id) from Author");
authorcount = (BigInteger) sqlQuery.uniqueResult();
}
return authorcount;
}
}
@@ -0,0 +1,58 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs.util;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
/**
* This class simply returns one instance of {@link SessionFactory} initialized when the application
* is started.
*/
@Slf4j
public class HibernateUtil {
private static final SessionFactory SESSIONFACTORY = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
// configures settings from hibernate.cfg.xml
final var registry = new StandardServiceRegistryBuilder().configure().build();
try {
return new MetadataSources(registry).buildMetadata().buildSessionFactory();
} catch (Exception ex) {
StandardServiceRegistryBuilder.destroy(registry);
LOGGER.error("Initial SessionFactory creation failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return SESSIONFACTORY;
}
}
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:test</property>
<property name="connection.username">sa</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="com.iluwatar.cqrs.domain.model.Author" />
<mapping class="com.iluwatar.cqrs.domain.model.Book" />
</session-factory>
</hibernate-configuration>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,113 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.cqrs;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.iluwatar.cqrs.commandes.CommandServiceImpl;
import com.iluwatar.cqrs.dto.Author;
import com.iluwatar.cqrs.dto.Book;
import com.iluwatar.cqrs.queries.QueryService;
import com.iluwatar.cqrs.queries.QueryServiceImpl;
import java.math.BigInteger;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* Integration test of IQueryService and ICommandService with h2 data
*/
class IntegrationTest {
private static QueryService queryService;
@BeforeAll
static void initializeAndPopulateDatabase() {
var commandService = new CommandServiceImpl();
queryService = new QueryServiceImpl();
// create first author1
commandService.authorCreated("username1", "name1", "email1");
// create author1 and update all its data
commandService.authorCreated("username2", "name2", "email2");
commandService.authorEmailUpdated("username2", "new_email2");
commandService.authorNameUpdated("username2", "new_name2");
commandService.authorUsernameUpdated("username2", "new_username2");
// add book1 to author1
commandService.bookAddedToAuthor("title1", 10, "username1");
// add book2 to author1 and update all its data
commandService.bookAddedToAuthor("title2", 20, "username1");
commandService.bookPriceUpdated("title2", 30);
commandService.bookTitleUpdated("title2", "new_title2");
}
@Test
void testGetAuthorByUsername() {
var author = queryService.getAuthorByUsername("username1");
assertEquals("username1", author.getUsername());
assertEquals("name1", author.getName());
assertEquals("email1", author.getEmail());
}
@Test
void testGetUpdatedAuthorByUsername() {
var author = queryService.getAuthorByUsername("new_username2");
var expectedAuthor = new Author("new_name2", "new_email2", "new_username2");
assertEquals(expectedAuthor, author);
}
@Test
void testGetBook() {
var book = queryService.getBook("title1");
assertEquals("title1", book.getTitle());
assertEquals(10, book.getPrice(), 0.01);
}
@Test
void testGetAuthorBooks() {
var books = queryService.getAuthorBooks("username1");
assertEquals(2, books.size());
assertTrue(books.contains(new Book("title1", 10)));
assertTrue(books.contains(new Book("new_title2", 30)));
}
@Test
void testGetAuthorBooksCount() {
var bookCount = queryService.getAuthorBooksCount("username1");
assertEquals(new BigInteger("2"), bookCount);
}
@Test
void testGetAuthorsCount() {
var authorCount = queryService.getAuthorsCount();
assertEquals(new BigInteger("2"), authorCount);
}
}
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:test</property>
<property name="connection.username">sa</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="com.iluwatar.cqrs.domain.model.Author" />
<mapping class="com.iluwatar.cqrs.domain.model.Book" />
</session-factory>
</hibernate-configuration>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright © 2014-2021 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>