cross join in SpringBoot 2.1.4.RELEASE app - spring-boot

I have a SpringBoot 2.1.4.RELEASE RESTful Web Service app., using Spring Initializer, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file. I am using an inMemoryDatabase : H2 Database Engine
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
I have these objects:
#Entity
#Table(name="t_menu_alert_notification")
public class MenuAlertNotification implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonProperty("id")
private Long id;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
#JoinColumn(name = "menu_alert_id")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="name")
#JsonIdentityReference(alwaysAsId=true)
protected MenuAlert menuAlert;
...
}
#Entity
#Table(name="t_menu_alert")
public class MenuAlert implements Serializable {
public MenuAlert() {
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "menu_id")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="name")
#JsonIdentityReference(alwaysAsId=true)
Menu menu;
..
}
#Entity
#Table(name = "t_menu")
#JsonPropertyOrder({ "id", "name", "address", "description" })
public class Menu implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonProperty("id")
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
#JsonIgnore
private User user;
..
}
I have this method in the repository class that extends from a CrudRepository
#Transactional
#Modifying
#Query("update MenuAlertNotification n set n.read = :status where n.id in :notificationIdList and n.menuAlert.menu.user.id = :userId")
void changeMenuNotificationListReadStatus( #Param("notificationIdList") List<Long> notificationIdList,
#Param("userId") long userId,
#Param("status") boolean status);
}
But when I run this method I have this error:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [update t_menu_alert_notification cross join set is_read=? where (id in (?)) and user_id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:279)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 51 more
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "UPDATE T_MENU_ALERT_NOTIFICATION CROSS[*] JOIN SET IS_READ=? WHERE (ID IN (?)) AND USER_ID=? "; expected "., AS, SET"; SQL statement:
update t_menu_alert_notification cross join set is_read=? where (id in (?)) and user_id=? [42001-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.getSyntaxError(DbException.java:217)
at org.h2.command.Parser.getSyntaxError(Parser.java:555)
at org.h2.command.Parser.read(Parser.java:3518)
at org.h2.command.Parser.parseUpdateSetClause(Parser.java:785)
at org.h2.command.Parser.parseUpdate(Parser.java:780)
at org.h2.command.Parser.parsePrepared(Parser.java:485)
at org.h2.command.Parser.parse(Parser.java:335)
at org.h2.command.Parser.parse(Parser.java:311)
at org.h2.command.Parser.prepareCommand(Parser.java:278)
at org.h2.engine.Session.prepareLocal(Session.java:611)
at org.h2.engine.Session.prepareCommand(Session.java:549)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1247)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:76)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:304)
at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:311)
at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$1.doPrepare(StatementPreparerImpl.java:87)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 73 more

According to the official documentation:
No joins, either implicit or explicit, can be specified in a bulk HQL
query.
So you need to find n.menuAlert first, then pass as parameter to update query or using native query.

Related

"Could not prepare statement" OneToMany

Here is what I'm trying to achieve :
Write a web service that gives the details of a repository: id, name, user name and
list of commits.
💡 It needs to be returned as a JSON format, for example :
{
"repository_id": "1",
"repository_name": "My repo",
"owner": "Noah",
"commits": [
"First commit",
"Second commit",
"Third commit"
]
}
You will find the database structure below :
Here is my CrudRepository with the query I am trying to build:
public interface RepositoriesDB extends CrudRepository<Repository, String> {
#Query(value = "SELECT r.repositoryId, r.repositoryName, r.owner.userName, r.commits FROM Repository r WHERE r.repositoryId = :repoId")
List<Object[]> getRepo(#Param("repoId") long repoId);
}
My User class :
#Entity
#NoArgsConstructor
#Data
public class User {
#NotNull
#Id
private String userLogin;
#NotBlank
#NotNull
private String userName;
#OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnore
private List<Repository> repositories;
}
My Repository class :
#Entity
#NoArgsConstructor
#Data
public class Repository {
#NotNull
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long repositoryId;
#NotNull
#NotBlank
#Size(min = 3, max = 25)
private String repositoryName;
#OneToMany(mappedBy = "repository", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnore
private List<Commit> commits;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "owner_login", nullable = false)
private User owner;
}
My Commit class :
#Entity
#NoArgsConstructor
#Data
public class Commit {
#NotNull
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long commitId;
#NotBlank
#NotNull
private LocalDateTime date = LocalDateTime.now();
#NotNull
#NotBlank
#Size(min = 1, max = 255)
private String message;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "repository_id", nullable = false)
private Repository repository;
}
And finally, here is the stacktrace :
There was an unexpected error (type=Internal Server Error, status=500).
could not prepare statement; SQL [select repository0_.repository_id as col_0_0_, repository0_.repository_name as col_1_0_, user1_.user_name as col_2_0_, . as col_3_0_, commits2_.commit_id as commit_i1_0_, commits2_.date as date2_0_, commits2_.message as message3_0_, commits2_.repository_id as reposito4_0_ from repository repository0_ cross join user user1_ inner join commit commits2_ on repository0_.repository_id=commits2_.repository_id where repository0_.owner_login=user1_.user_login and repository0_.repository_id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select repository0_.repository_id as col_0_0_, repository0_.repository_name as col_1_0_, user1_.user_name as col_2_0_, . as col_3_0_, commits2_.commit_id as commit_i1_0_, commits2_.date as date2_0_, commits2_.message as message3_0_, commits2_.repository_id as reposito4_0_ from repository repository0_ cross join user user1_ inner join commit commits2_ on repository0_.repository_id=commits2_.repository_id where repository0_.owner_login=user1_.user_login and repository0_.repository_id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:259)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)
[...]
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
[...]
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "SELECT REPOSITORY0_.REPOSITORY_ID AS COL_0_0_, REPOSITORY0_.REPOSITORY_NAME AS COL_1_0_, USER1_.USER_NAME AS COL_2_0_, .[*] AS COL_3_0_, COMMITS2_.COMMIT_ID AS COMMIT_I1_0_, COMMITS2_.DATE AS DATE2_0_, COMMITS2_.MESSAGE AS MESSAGE3_0_, COMMITS2_.REPOSITORY_ID AS REPOSITO4_0_ FROM REPOSITORY REPOSITORY0_ CROSS JOIN USER USER1_ INNER JOIN COMMIT COMMITS2_ ON REPOSITORY0_.REPOSITORY_ID=COMMITS2_.REPOSITORY_ID WHERE REPOSITORY0_.OWNER_LOGIN=USER1_.USER_LOGIN AND REPOSITORY0_.REPOSITORY_ID=?"; expected "*, NOT, EXISTS, INTERSECTS, UNIQUE"; SQL statement:
select repository0_.repository_id as col_0_0_, repository0_.repository_name as col_1_0_, user1_.user_name as col_2_0_, . as col_3_0_, commits2_.commit_id as commit_i1_0_, commits2_.date as date2_0_, commits2_.message as message3_0_, commits2_.repository_id as reposito4_0_ from repository repository0_ cross join user user1_ inner join commit commits2_ on repository0_.repository_id=commits2_.repository_id where repository0_.owner_login=user1_.user_login and repository0_.repository_id=? [42001-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:453)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
at org.h2.message.DbException.getSyntaxError(DbException.java:243)
at org.h2.command.Parser.getSyntaxError(Parser.java:1053)
[...]
I believe the problem comes from the fact that I'm trying to select a OneToMany relation, since I don't have this issue when selecting the owner because I have an #JsonIgnore annotation and infinite loops...
Except, in this case, I NEED to select the list of transaction :(
Thanks in advance for your help !
The error in your sql query is the r.commits part. It is a list of values and sql column accept only a single (or scalar) value type like number, varchar etc
Since the relation between Repository and Commit entities isOne-To-Many association so r.commits is a list of values so Hibernate fails to prepare the sql statement.
You can remove the r.commits part from your sql query and it will works.
If you would like to get the list of commits for your repository, you can implement a specefic method for that.
Something like
public interface CommitRepository extends JpaRepository<Commit, Long> {
List<Commit> findAllByRepository(Repository repository);
}
you can pass to this method the repository object that you want to get all the associated commits.
Also, since the Repository.repositoryId is Long data type so you have to change the RepositoriesDB defenition to
public interface RepositoriesDB extends JpaRepository<Repository, Long>

#GeneratedValue annotation is not working on mapping table

I have a many to many relationship like below.
#Entity
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_ID")
private int id;
private String firstName;
private String lastName;
#JoinTable(name = "employee_project_mapping", joinColumns = #JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "EMP_ID"), inverseJoinColumns = #JoinColumn(name = "PROJECT_ID", referencedColumnName = "PJT_ID"))
#JsonManagedReference
#ManyToMany(cascade = CascadeType.ALL)
Set<Project> projects = new HashSet<Project>();
.....
.....
}
#Entity
#Table(name = "projects")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PJT_ID")
private int projectId;
private String projectName;
private int teamSize;
#ManyToMany(mappedBy = "projects")
#JsonBackReference
private Set<Employee> emps = new HashSet<Employee>();
.....
.....
}
#Entity
#Table(name = "employee_project_mapping")
public class EmployeeProjectMapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_PJT_ID")
private Integer empPjtId;
#Column(name = "PROJECT_ID")
private Integer projectId;
#Column(name = "EMPLOYEE_ID")
private Integer emploeeId;
.....
.....
}
But when I am trying to insert an employee object with set of projects, it is failing to create auto generated id for the column EMP_PJT_ID (this is an id to the mapping table record). Can't I add an auto generated id for mapping table using jpa?
Error trace
Hibernate: insert into employees (emp_id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into employee_project_mapping (employee_id, project_id) values (?, ?)
2021-04-22 23:34:25.973 ERROR 24126 --- [nio-8080-exec-9] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "EMP_PJT_ID"; SQL statement:
insert into employee_project_mapping (employee_id, project_id) values (?, ?) [23502-200]
2021-04-22 23:34:25.975 ERROR 24126 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column "EMP_PJT_ID"; SQL statement:
insert into employee_project_mapping (employee_id, project_id) values (?, ?) [23502-200]
The mapping of a many-to-many should be:
#Entity
#Table(name = "employees")
public class Employee {
...
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, orphanRemoval = true)
Set<EmployeeProjectMapping> projects = new HashSet<EmployeeProjectMapping>();
...
// Utility method to update both sides of the association
public void addProject(Project project) {
EmployeeProjectMapping empProject = new PersEmployeeProjectMappingonAddress( this, project );
projects.add( empProject );
project.getEmployees().add( empProject );
}
}
#Entity
#Table(name = "projects")
public class Project {
...
#OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<EmployeeProjectMapping> emps = new HashSet<Employee>();
...
}
#Entity
#Table(name = "employee_project_mapping")
public class EmployeeProjectMapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_PJT_ID")
private Integer empPjtId;
#Id
#ManyToOne
#JoinColumn(name = "PROJECT_ID")
private Project project;
#Id
#ManyToOne
#JoinColumn(name = "EMPLOYEE_ID")
private Employee employee;
.....
.....
}
Make sure to check the example on the Hibernate ORM documentation for all the details.

Problem Retrieving Nextval in JPA Application

I need have a need to return nextVal at various times in my application. I have an entity class like the following:
#Entity
#Table(name = "TBL_CACL")
public class Cacl {
#Id
#SequenceGenerator(name = "caclGenerator", sequenceName = "caclSeq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "calcGenerator")
#Column(name = "ID")
private Integer id;
// more stuff below....
, and I added the following in my repository interface:
#Repository
public interface CaclRepository extends JpaRepository<Cacl, Integer> {
#Query(value = "SELECT caclSeq.nextval FROM Cacl", nativeQuery = true)
Long getNextSeriesId();
However when I attempt to read it like this:
long nextval = caclRepository.getNextSeriesId() + 1;
, I get this exception:
(can't show entire stack trace)
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: relation "cacl" does not exist
Its puzzling to me that I am getting error "cacl does not exist" because this application has been up and working for some time. All that I have done is add the #SequenceGenerator, updated the #GeneratorValue to link to the #SequenceGenerator annotation, and create the new query. I would be grateful for any ideas as to what I am doing wrong. thanks
My answer is based on simplifying my approach some. Now I am simply using the default sequences supplied by postgress. So for instance now I have:
#Entity
#Table(name = "TBL_CACL")
public class Cacl {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Integer id;
#Column(name="NAME")
private String name;
// more stuff below...
, then in the repository (after querying postgress to get default sequences) I have:
#Query(value = "select last_value from tbl_cacl_id_seq", nativeQuery = true)
public Integer getCurrentVal();
And then:
int nextval = caclRepository.getCurrentVal();
works fine.
you could try removing the native query
#Query(value = "SELECT nextval('caclSeq')", nativeQuery =
true)
Long getNextSeriesId();

ERROR: UPDATE or DELETE statement on table

In a project with Spring Boot and Spring JPA I Have two entities FunctionConfiguration and InvokeFunctionResult.
#Entity
#Table(name = "function_configuration")
public class FunctionConfigurationEntity {
#Id
#Column(name = "id_function_configuration")
#GeneratedValue(strategy = IDENTITY)
private Integer idFunctionConfiguration;
}
#Entity
#Table(name = "invoked_function_result")
public class InvokedFunctionResultEntity {
#Id
#Column(name = "id_invoked_result_function")
#GeneratedValue(strategy = IDENTITY)
private Integer idInvokedResultFunction;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "function_configuration_id", nullable = false, foreignKey = #ForeignKey(name = "function_configuration_fk"), referencedColumnName = "id_function_configuration")
private FunctionConfigurationEntity functionConfiguration;
}
The InvokeFunctionResult has foreign key the id of the FunctionConfiguration.
If I try to do a delete with an id of a functionConfiguration that is present in the InvokeFunctionResult:
#Transactional
#Modifying
#Query(value = "DELETE FROM FunctionConfigurationEntity fce WHERE fce.idFunctionConfiguration = idFunctionConfiguration")
void deleteByFunctionConfigurationId(#Param("idFunctionConfiguration") Integer functionConfigurationId);
I get the following error: Caused by: org.postgresql.util.PSQLException: ERROR: UPDATE or DELETE statement on table "function_configuration" violates foreign key constraint "function_configuration_fk" on table "invoked_function_result"
How can I fix it?

Select a unique names from Users that have more than 3 Articles. Spring Data, H2

I use: Spring Boot, Spring Data, and H2 (in-memory) DataBase.
DB TABLES:
CREATE TABLE user
(
id INT AUTO_INCREMENT,
name VARCHAR(250) NOT NULL,
age INT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE article
(
id INT AUTO_INCREMENT,
text TEXT NOT NULL,
color ENUM ('red', 'green', 'blue', 'yellow', 'pink') NOT NULL,
user_id INT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE ON UPDATE CASCADE
);
In ArticleRepository exploited such query:
SELECT u.name, a.user_id, count() FROM user AS u INNER JOIN article AS a ON u.id = a.user_id GROUP BY a.user_id HAVING COUNT() > 3;
#Repository
public interface ArticleRepository extends JpaRepository<Article, Integer> {
#Query(value = "SELECT u.name, a.user_id, count(*) FROM user AS u INNER JOIN article AS a ON u.id = a.user_id GROUP BY a.user_id HAVING COUNT(*) > 3", nativeQuery = true)
List<Article> findUserNamesByArticlesCountMoreThan();
}
After request I receive the error:
In Postman:
"error": "Internal Server Error", "message": "could not execute query;
SQL [SELECT u.name, a.user_id, count(text) FROM user AS u INNER JOIN
article AS a ON u.id = a.user_id GROUP BY a.user_id HAVING COUNT(*) >
3]; nested exception is org.hibernate.exception.SQLGrammarException:
could not execute query",
In IntelliJ Idea:
02:54:24.681 [http-nio-9090-exec-1] WARN SqlExceptionHelper - SQL
Error: 42122, SQLState: 42S22 02:54:24.681 [http-nio-9090-exec-1]
ERROR SqlExceptionHelper - Column "id" not found [42122-197]
02:54:24.703 [http-nio-9090-exec-1] ERROR [dispatcherServlet] -
Servlet.service() for servlet [dispatcherServlet] in context with path
[] threw exception [Request processing failed; nested exception is
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not execute query; SQL [SELECT u.name, a.user_id, count(text) FROM
user AS u INNER JOIN article AS a ON u.id = a.user_id GROUP BY
a.user_id HAVING COUNT(*) > 3]; nested exception is
org.hibernate.exception.SQLGrammarException: could not execute query]
with root cause org.h2.jdbc.JdbcSQLException: Column "id" not found
[42122-197] at
org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.get(DbException.java:179) at
org.h2.message.DbException.get(DbException.java:155) at
org.h2.jdbc.JdbcResultSet.getColumnIndex(JdbcResultSet.java:3148) at
org.h2.jdbc.JdbcResultSet.get(JdbcResultSet.java:3247) at
org.h2.jdbc.JdbcResultSet.getInt(JdbcResultSet.java:346)..............
Help me to resolve this problem, and find a mistake.
Entities:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "article")
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#Column(name = "text", nullable = false)
private String text;
#Column(name = "color", nullable = false, unique = true)
#Enumerated(EnumType.STRING)
private Color color;
#JsonIgnore
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
#JoinColumn(name = "user_id", referencedColumnName="id")
private User user;
}
.
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#ToString(exclude = "articles")
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "age", nullable = false)
private Integer age;
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<Article> articles;
}
Service:
#Service
public class ArticleService {
private ArticleRepository articleRepository;
#Autowired
public ArticleService(ArticleRepository articleRepository) {
this.articleRepository = articleRepository;
}
public List<Article> findAllUserNamesByArticlesMoreThan() {
return articleRepository.findUserNamesByArticlesCountMoreThan(); }}
ArticleDtoService:
#Service
public class ArticleDtoService {
private ArticleService articleService;
#Autowired
public ArticleDtoService(ArticleService articleService) {
this.articleService = articleService;
}
public ResponseEntity<List<ArticleDto>> getAllUserNamesByArticlesMoreThan() {
List<Article> articles = articleService.findAllUserNamesByArticlesMoreThan();
Link link = linkTo(methodOn(ArticleController.class).getAllUserNamesListByArticlesMoreThan()).withSelfRel();
return new ResponseEntity<>(createArticleDtoList(articles, link), HttpStatus.OK); }}
ArticleController:
#RestController
public class ArticleController {
private final ArticleDtoService articleDtoService;
#Autowired
public ArticleController(ArticleDtoService articleDtoService) {
this.articleDtoService = articleDtoService;
}
#GetMapping(value = "/api/articles/count")
public ResponseEntity<List<ArticleDto>> getAllUserNamesListByArticlesMoreThan() {
return articleDtoService.getAllUserNamesByArticlesMoreThan(); }}
ArticleDto:
public class ArticleDto extends ResourceSupport {
public Article article;
public ArticleDto(Article article, Link selfLink) {
this.article = article;
add(selfLink); }}

Resources