Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions command-query-responsibility-segregation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,12 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.15.Final</version>
<version>6.4.4.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Hibernate 6 migration issue as above, but for Book retrieval by title. Consider using getSingleResult() with appropriate exception handling or getResultList() to guard against multiple results.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orbisai0security can you address code review comments?

<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<version>4.0.5</version>
</dependency>
</dependencies>
<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.iluwatar.cqrs.domain.model.Author;
import com.iluwatar.cqrs.domain.model.Book;
import com.iluwatar.cqrs.util.HibernateUtil;
import jakarta.persistence.NoResultException;
import org.hibernate.SessionFactory;

/**
Expand All @@ -38,39 +39,35 @@ 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");
var query = session.createQuery("from Author where username=:username", Author.class);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential NonUniqueResultException if username is not unique; consider enforcing a unique constraint on the username column and/or handling NonUniqueResultException to avoid runtime failures.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orbisai0security can you address code review comments?

query.setParameter("username", username);
author = (Author) query.uniqueResult();
try {
return query.getSingleResult();
} catch (NoResultException e) {
throw new IllegalArgumentException("Author " + username + " doesn't exist!");
}
Comment on lines +47 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not close the global SessionFactory when a query returns no result. Closing the SessionFactory will make subsequent DB operations fail. Prefer returning a null/Optional or throwing a domain-specific exception instead of a NullPointerException.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orbisai0security can you address code review comments?

}
Comment on lines +43 to 50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When creating a typed query, use getSingleResult instead of uniqueResult() in Hibernate 6 to avoid deprecation/removal. If you must keep uniqueResult(), wrap in try/catch to handle NonUniqueResultException.

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");
var query = session.createQuery("from Book where title=:title", Book.class);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar risk as above for fetching a Book by title. Ensure title column is unique or handle multiple results gracefully.

query.setParameter("title", title);
book = (Book) query.uniqueResult();
}
if (book == null) {
HibernateUtil.getSessionFactory().close();
throw new NullPointerException("Book " + title + " doesn't exist!");
try {
return query.getSingleResult();
} catch (NoResultException e) {
Comment on lines 54 to +59

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar issue for missing Book: avoid closing the SessionFactory on NoResultException and avoid throwing a NullPointerException. Align behavior with author lookup or return null.

throw new IllegalArgumentException("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.persist(author);
session.getTransaction().commit();
}
}
Expand All @@ -81,7 +78,7 @@ public void bookAddedToAuthor(String title, double price, String username) {
var book = new Book(title, price, author);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.save(book);
session.persist(book);
session.getTransaction().commit();
}
}
Expand All @@ -92,7 +89,7 @@ public void authorNameUpdated(String username, String name) {
author.setName(name);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.merge(author);
session.getTransaction().commit();
}
}
Expand All @@ -103,7 +100,7 @@ public void authorUsernameUpdated(String oldUsername, String newUsername) {
author.setUsername(newUsername);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.merge(author);
session.getTransaction().commit();
}
}
Expand All @@ -114,7 +111,7 @@ public void authorEmailUpdated(String username, String email) {
author.setEmail(email);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(author);
session.merge(author);
session.getTransaction().commit();
}
}
Expand All @@ -125,7 +122,7 @@ public void bookTitleUpdated(String oldTitle, String newTitle) {
book.setTitle(newTitle);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(book);
session.merge(book);
session.getTransaction().commit();
}
}
Expand All @@ -136,7 +133,7 @@ public void bookPriceUpdated(String title, double price) {
book.setPrice(price);
try (var session = sessionFactory.openSession()) {
session.beginTransaction();
session.update(book);
session.merge(book);
session.getTransaction().commit();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
*/
package com.iluwatar.cqrs.domain.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
Expand All @@ -42,7 +43,9 @@ public class Author {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(unique = true)
private String username;

private String name;
private String email;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
*/
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 jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
Expand All @@ -46,7 +47,9 @@ public class Book {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(unique = true)
private String title;

private double price;
@ManyToOne private Author author;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.iluwatar.cqrs.dto.Author;
import com.iluwatar.cqrs.dto.Book;
import com.iluwatar.cqrs.util.HibernateUtil;
import jakarta.persistence.NoResultException;
import java.math.BigInteger;
import java.util.List;
import org.hibernate.SessionFactory;
Expand All @@ -43,30 +44,36 @@ public class QueryServiceImpl implements QueryService {

@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");
+ " from com.iluwatar.cqrs.domain.model.Author a where a.username=:username",
Author.class);
sqlQuery.setParameter(AppConstants.USER_NAME, username);
authorDto = sqlQuery.uniqueResult();
try {
return sqlQuery.getSingleResult();
} catch (NoResultException e) {
return null;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This typed HQL uses uniqueResult on a typed query. In Hibernate 6, getSingleResult() is preferred, and exceptions should be handled to cover no result or multiple results. Consider switching to getSingleResult() with try/catch or getResultList() with a single element check.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated uniqueResult on typed query; migrate to getSingleResult with proper exception handling.

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");
+ " from com.iluwatar.cqrs.domain.model.Book b where b.title=:title",
Book.class);
sqlQuery.setParameter("title", title);
bookDto = sqlQuery.uniqueResult();
try {
return sqlQuery.getSingleResult();
} catch (NoResultException e) {
return null;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See note above about uniqueResult in Hibernate 6 for book DTO retrieval. Prefer getSingleResult() or safe getResultList() usage.

return bookDto;
}

@Override
Expand All @@ -77,7 +84,8 @@ public List<Book> getAuthorBooks(String username) {
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");
+ "where b.author.id = a.id and a.username=:username",
Book.class);
sqlQuery.setParameter(AppConstants.USER_NAME, username);
bookDtos = sqlQuery.list();
}
Expand All @@ -86,26 +94,31 @@ public List<Book> getAuthorBooks(String username) {

@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");
+ " where b.author_id = a.id and a.username=:username",
Long.class);
sqlQuery.setParameter(AppConstants.USER_NAME, username);
bookcount = (BigInteger) sqlQuery.uniqueResult();
try {
return BigInteger.valueOf(sqlQuery.getSingleResult());
} catch (NoResultException e) {
return BigInteger.ZERO;
}
}
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();
var sqlQuery = session.createNativeQuery("SELECT count(id) from Author", Long.class);
try {
return BigInteger.valueOf(sqlQuery.getSingleResult());
} catch (NoResultException e) {
return BigInteger.ZERO;
}
}
return authorcount;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace uniqueResult with getSingleResult or getResultList to handle null/no results and deprecation in Hibernate 6.

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
package com.iluwatar.dependency.injection;

import javax.inject.Inject;
import jakarta.inject.Inject;

/**
* GuiceWizard implements inversion of control. Its dependencies are injected through its
Expand Down
5 changes: 0 additions & 5 deletions metadata-mapping/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@
<artifactId>hibernate-core</artifactId>
<version>6.6.11.Final</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

package com.iluwatar.polling;

import jakarta.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Repository;

/** Data repository to keep or store data. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package com.iluwatar.polling;

import jakarta.annotation.PreDestroy;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -92,7 +93,7 @@ public Map<Integer, String> getAllData() {
return repository.findAll();
}

@javax.annotation.PreDestroy
@PreDestroy
public void shutdown() {
scheduler.shutdown();
}
Expand Down
8 changes: 4 additions & 4 deletions polling-publisher/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@
<version>${spring-boot.version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<!-- https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
Expand Down
23 changes: 6 additions & 17 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- Spring Boot related dependencies. Keep these in sync! -->
<spring-boot.version>3.4.5</spring-boot.version>
<junit.version>5.11.4</junit.version>
<spring-boot.version>3.5.14</spring-boot.version>
<junit.version>5.12.2</junit.version>
<mockito.version>5.14.2</mockito.version>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spring Boot version configured to 3.5.14 and JUnit version 5.12.2. The PR title mentions 4.0.6; make sure the intended target aligns with your upgrade plan and CI compatibility.

<logback.version>1.5.18</logback.version>
<slf4j.version>2.0.17</slf4j.version>
Expand Down Expand Up @@ -314,22 +314,11 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
Loading
Loading