JpaRepostory existsXXX method don't working properly - spring-boot

I need to check is user with a specified id and token exists. Tokens are stored in #ElementCollection set. I tried to write a derived query method in my repository like this:
boolean existsByIdAndTokensContains(long id, String token);
But that isn't working (returns false for right input values).
When I tried to specify query explicitly it start working right:
#Query("select (count(u) > 0) from users as u where u.id = :id and :token member of u.tokens")
The most strange that Hibernate logs are looking similar for both queries:
For the derived query:
/* select
generatedAlias0.id
from
users as generatedAlias0
where
(
generatedAlias0.id=:param0
)
and (
:param1 member of generatedAlias0.tokens
) */ select
userentity0_.id as col_0_0_
from
users userentity0_
where
userentity0_.id=?
and (
? in (
select
tokens1_.token
from
users_tokens tokens1_
where
userentity0_.id=tokens1_.user_id
)
) limit ?
For the explicit query:
/* select
(count(u) > 0)
from
users as u
where
u.id = :id
and :token member of u.tokens */ select
count(userentity0_.id)>0 as col_0_0_
from
users userentity0_
where
userentity0_.id=?
and (
? in (
select
tokens1_.token
from
users_tokens tokens1_
where
userentity0_.id=tokens1_.user_id
)
)
And when I tried to query generated query, result contained the right user.
What am I do wrong?

I would think you need to implement an Attribute Converter to convert the id into a Boolean. This way it will know how to map a not null Id to a true value.

Ok, I found the solution.
For my Set of tokens:
#ElementCollection
#Column(name = "token", nullable = false)
#CollectionTable(name = "users_tokens", joinColumns = #JoinColumn(name = "user_id"),
uniqueConstraints = #UniqueConstraint(columnNames = {"user_id", "token"}))
private final Set<String> tokens;
Works the similar query but without Contains:
boolean existsByIdAndTokens(long id, String token);
I don't know is it a bug, but this works for me.

Related

Insert data and get back id in mybatis

I should save the record in the database and get the record id in the response. After a long search and research I came up with the following option.
data class User(
val id: UUID? = null,
val username: String,
...
)
UserRepo:
#Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
#Insert("""
INSERT INTO "user" (
username,
...
) VALUES (
#{username},
...
)
""")
fun save(user: User): User
in response I get the following.
org.apache.ibatis.binding.BindingException: Mapper method '...UserRepository.save' has an unsupported return type: class ...entity.User
in the following case, I don't get an error, but I don't get an id either, how can I do it correctly? Used Select instead of Insert
#Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
#Select("""
INSERT INTO "user" (
username
) VALUES (
#{username}
)
""")
fun save(user: User): User
if we solve my first question, then I would like to know if it is possible to get the answer not in the User class, but in another one, for example, UserResponse? That is, send a request to the User class, and receive a response in the UserResponse
UPDATE
I was able to get the id after changing the id type to String.
Like this:
data class User(
val id: String? = null,
val username: String,
...
)
Apparently some settings are needed for UUID?
Has anyone faced such a problem?

pgp_sym_decrypt not working with JPA nativeQuery. Always throw error

Hi I'm working on a Spring Boot Project using PSQL. I have a model that is implemented pgcrypto like this,
#ColumnTransformer(
read = "pgp_sym_decrypt( msisdn::bytea, 'mypassword' )",
write = "pgp_sym_encrypt( ?, 'mypassword' )"
)
#Column(name="msisdn")
private String msisdn;
In my JPArepository every function like find(), findAll(), findBySomthing(..) work perfectly. The result decoded my msisdn record correctly.
But it's not working on a navtiveQuery. For example in my JPArepository,
#Query(value = "SELECT id, pgp_sym_decrypt( msisdn::bytea, 'mypassword' ) as msisdn FROM tbl_payments ORDER BY id ASC;", nativeQuery = true)
List<MyClass> test();
It always throws error
org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
But the query is correct because I already copied it to do a query directly on Database.
Do I need anything extra to work with JPA nativeQuery ?
Please help. Thanks a lot.
Your query:
#Query(value = "SELECT id, pgp_sym_decrypt( msisdn::bytea, 'mypassword' ) as msisdn FROM tbl_payments ORDER BY id ASC;", nativeQuery = true)
List<MyClass> test();
just add \:\: at :: in bytea
Improved query:
#Query(value = "SELECT id, pgp_sym_decrypt( msisdn\\:\\:bytea, 'mypassword' ) as msisdn FROM tbl_payments ORDER BY id ASC;", nativeQuery = true)
List<MyClass> test();

Map new column from Spring Native query to entity

I have a case statement in my Native query where I am attempting to override a field in my entity.
SELECT i.id, i.ONE_TO_ONE_ID, i.ANOTHER, CASE(WHEN condition THEN 'YES' WHEN another_condition THEN 'NO' ELSE 'MAYBE' END) as word ....
I am using this with JpaRepository as a native query, with pagination.
When I run the native query against my db directly, the result set looks as though I expect.
| id_value | MAPPED_ENTITY_ID_value | another value | word_value (YES) |
When I run the native query from my JpaRepository, everything works there, except word is always null. I cant' seem to figure out how to map the additional String word result to a field in my Entity.
Is there a way to get this to map? Or will I have to create an entire #SqlResultSetMapping() for all of my fields coupled with a native query? (hoping not)
UPDATE: 1
I was generalizing above. Here is my Query.
#Query(
name = "listPagedMapping",
value = "SELECT DISTINCT i.ID, i.INSTANCE_ID, i.REGION, i.CNAME_STACK_ID, i.INSTANCE_STATE, i.IP_ADDRESS, i.EC2_ROLE_NAME, i.INSTANCE_OWNER, i.IS_MASTER, i.EC2_MASTER_ID, i.CNAME, i.EC2_START_TIMESTAMP, i.PRIVATE_DNS, i.INSTANCE_NAME, i.AUTO_TERMINATE, i.AUTO_TERMINATE_DATE, i.TERMINATION_ZONE, i.ADMIN_GROUP_AD_LDAP_ID, i.USER_GROUP_AD_LDAP_ID, (CASE WHEN i.INSTANCE_OWNER=:username THEN 'OWNER' WHEN i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) THEN 'ADMIN' WHEN i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) THEN 'USER' END) as PERMISSION FROM USER u, USER_ACCESS_GROUPS g, EC2_PROVISIONING i WHERE i.INSTANCE_OWNER=:username and i.INSTANCE_STATE in (:instanceStates) or u.username=:username and i.INSTANCE_STATE in (:instanceStates) and g.USER_ID=u.USER_ID and (i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) or i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID))",
countQuery = "SELECT count(*) FROM (SELECT DISTINCT i.* FROM USER u, USER_ACCESS_GROUPS g, EC2_PROVISIONING i WHERE i.INSTANCE_OWNER=:username and i.INSTANCE_STATE in (:instanceStates) or u.username=:username and i.INSTANCE_STATE in (:instanceStates) and g.USER_ID=u.USER_ID and (i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) or i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID))) as ug",
nativeQuery = true)
Page<Ec2Instance> findAllByPermissionUserAdminOrOwnerAndInstanceStateIn(
#Param("username")final String username,
#Param("instanceStates") final Set<String> instanceStates,
final Pageable pageable);
}
Obviously a bit more complex.
I can get it to map to the entity field with using a named query, but then I loose all the default mappings:
#JsonInclude(JsonInclude.Include.NON_NULL)
#SuppressWarnings("unused")
#Data
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(exclude={"masterNode", "workers", "associatedBuckets"})
#Entity
#Table(name = "EC2_PROVISIONING")
#SqlResultSetMapping(
name="listPagedMapping",
columns = {
#ColumnResult(name = "permission", type = String.class)
}
)
#NamedNativeQuery(
name = "listAccessibleInstances",
query = ACCESSIBLE_QUERY,
resultSetMapping = "listPagedMapping"
)
public class Ec2Instance {
....
private String permission;
#column(name = "INSTANCE_ID")
private String instanceId;
#ManyToOne
#JoinColumn(name = "EC2_MASTER_ID")
private Ec2Instance masterNode;
#Setter(AccessLevel.NONE)
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "WORKER_EC2_NODES", joinColumns = { #JoinColumn(name = "EC2_MASTER_ID") }, inverseJoinColumns = {
#JoinColumn(name = "ID") })
private Set<Ec2Instance> workers = new HashSet<>();
... More fields ..
}
I guess, I am hoping there is a way to provide a single mapping on-top of the default mapping that is done by ORM. The above code results in only a pageable of Content PERMISSION, rather than the whole entity + permission.
UPDATE: 2
Ok, so I am getting closer... Seems by removing the #ColumnResult I do get the default mapping, plus the PERMISSION field mapped over! Looks like this:
#SqlResultSetMapping(
name="listPagedMapping"
)
The last issue is it does not accept my CountQuery, and causes my tests to fail whenever a Pagination Query results with multiple pages. Looks like Spring try's to come up with its own CountQuery, which is not correct.
UPDATE: 3
To finish this off, looks like I can provide the Count Query as described here: Spring Data - Why it's not possible to have paging with native query
I will give this a go and update back.
I never got this to work quite how I wanted. I am sure I could by mapping my entire entity, but, that would have been painstaking. I ended up solving this by using NamedNativeQueries, with mapping for the additional Column as a result of my Case statement. My entity class is now annotated like:
#JsonInclude(JsonInclude.Include.NON_NULL)
#SuppressWarnings("unused")
#Data
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(callSuper = false)
#Entity
#Table(name = "EC2_PROVISIONING")
#SqlResultSetMappings({
#SqlResultSetMapping(
name = "listPagedMapping",
entities = {
#EntityResult(
entityClass = Ec2Instance.class
)
},
columns = {#ColumnResult(name = "permission", type = String.class)}
),
#SqlResultSetMapping(name = "listPagedMapping.count", columns = #ColumnResult(name = "cnt"))
})
#NamedNativeQueries({
#NamedNativeQuery(
name = "Ec2Instance.listAccessibleInstances",
query = ACCESSIBLE_QUERY,
resultClass = Ec2Instance.class,
resultSetMapping = "listPagedMapping"
),
#NamedNativeQuery(
name = "Ec2Instance.listAccessibleInstances.count",
resultSetMapping = "listPagedMapping.count",
query = ACCESSIBLE_QUERY_COUNT
)
})
We also dont need the permission field in this entity anymore. I removed that.
Then in my Repository:
Page<Object[]> listAccessibleInstances(
#Param("username")final String username,
#Param("instanceStates") final Set<String> instanceStates,
final Pageable pageable);
Thats it! Now the result of my case statement is returned with each entity.
Object[0] = original, default mapped entity.
Object[1] = permission

Spring Data and Native Query with pagination

In a web project, using latest spring-data (1.10.2) with a MySQL 5.6 database, I'm trying to use a native query with pagination but I'm experiencing an org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException at startup.
UPDATE: 20180306 This issue is now fixed in Spring 2.0.4 For those still interested or stuck with older versions check the related answers and comments for workarounds.
According to Example 50 at Using #Query from spring-data documentation this is possible specifying the query itself and a countQuery, like this:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
Out of curiosity, In NativeJpaQuery class I can see that it contains the following code to check if it's a valid jpa query:
public NativeJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, EvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
super(method, em, queryString, evaluationContextProvider, parser);
JpaParameters parameters = method.getParameters();
boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable") || queryString.contains("#sort");
if(hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
throw new InvalidJpaQueryMethodException("Cannot use native queries with dynamic sorting and/or pagination in method " + method);
}
}
My query contains a Pageable parameter, so hasPagingOrSortingParameter is true, but it's also looking for a #pageable or #sort sequence inside the queryString, which I do not provide.
I've tried adding #pageable (it's a comment) at the end of my query, which makes validation to pass but then, it fails at execution saying that the query expects one additional parameter: 3 instead of 2.
Funny thing is that, if I manually change containsPageableOrSortInQueryExpression from false to true while running, the query works fine so I don't know why it's checking for that string to be at my queryString and I don't know how to provide it.
Any help would be much appreciated.
Update 01/30/2018
It seems that developers at spring-data project are working on a fix for this issue with a PR by Jens Schauder
My apologies in advance, this is pretty much summing up the original question and the comment from Janar, however...
I run into the same problem: I found the Example 50 of Spring Data as the solution for my need of having a native query with pagination but Spring was complaining on startup that I could not use pagination with native queries.
I just wanted to report that I managed to run successfully the native query I needed, using pagination, with the following code:
#Query(value="SELECT a.* "
+ "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
+ "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time)"
+ "ORDER BY a.id \n#pageable\n",
/*countQuery="SELECT count(a.*) "
+ "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
+ "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time) \n#pageable\n",*/
nativeQuery=true)
public List<Author> findAuthorsUpdatedAndNew(Pageable pageable);
The countQuery (that is commented out in the code block) is needed to use Page<Author>
as the return type of the query, the newlines around the "#pageable" comment are needed to avoid the runtime error on the number of expected parameters (workaround of the workaround). I hope this bug will be fixed soon...
This is a hack for program using Spring Data JPA before Version 2.0.4.
Code has worked with PostgreSQL and MySQL :
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY ?#{#pageable}",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
ORDER BY ?#{#pageable} is for Pageable.
countQuery is for Page<User>.
Just for the record, using H2 as testing database, and MySQL at runtime, this approach works (example is newest object in group):
#Query(value = "SELECT t.* FROM t LEFT JOIN t AS t_newer " +
"ON t.object_id = t_newer.object_id AND t.id < t_newer.id AND o_newer.user_id IN (:user_ids) " +
"WHERE t_newer.id IS NULL AND t.user_id IN (:user_ids) " +
"ORDER BY t.id DESC \n-- #pageable\n",
countQuery = "SELECT COUNT(1) FROM t WHERE t.user_id IN (:user_ids) GROUP BY t.object_id, t.user_id",
nativeQuery = true)
Page<T> findByUserIdInGroupByObjectId(#Param("user_ids") Set<Integer> userIds, Pageable pageable);
Spring Data JPA 1.10.5, H2 1.4.194, MySQL Community Server 5.7.11-log (innodb_version 5.7.11).
I am adding this answer just as a placeholder for those users who are using more recent versions of Spring Boot. On Spring Boot 2.4.3, I observed that none of the workaround were necessary, and the following code worked straight out of the box for me:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value="SELECT * FROM USERS WHERE LASTNAME = ?1", nativeQuery=true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
The countQuery definition was not necessary, and a call to Page#getTotalElements() in fact already was returning the correct count, as returned by JPA's own internal count query.
The above code is extremely powerful, offering pagination made via a native query, yet which return results into actual Java entities (rather than the ugly and bulky List<Object[]>, which sometimes is necessary).
Try this:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY /*#pageable*/",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
("/* */" for Oracle notation)
I have exact same symptom like #Lasneyx. My workaround for Postgres native query
#Query(value = "select * from users where user_type in (:userTypes) and user_context='abc'--#pageable\n", nativeQuery = true)
List<User> getUsersByTypes(#Param("userTypes") List<String> userTypes, Pageable pageable);
I use oracle database and I did not get the result but an error with generated comma which d-man speak about above.
Then my solution was:
Pageable pageable = new PageRequest(current, rowCount);
As you can see without order by when create Pagable.
And the method in the DAO:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 /*#pageable*/ ORDER BY LASTNAME",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
I could successfully integrate Pagination in
spring-data-jpa-2.1.6
as follows.
#Query(
value = “SELECT * FROM Users”,
countQuery = “SELECT count(*) FROM Users”,
nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);
Both the following approaches work fine with MySQL for paginating native query. They doesn't work with H2 though. It will complain the sql syntax error.
ORDER BY ?#{#pageable}
ORDER BY a.id \n#pageable\n
Using "ORDER BY id DESC \n-- #pageable\n "
instead of "ORDER BY id \n#pageable\n" worked for me with MS SQL SERVER
This worked for me (I am using Postgres) in Groovy:
#RestResource(path="namespaceAndNameAndRawStateContainsMostRecentVersion", rel="namespaceAndNameAndRawStateContainsMostRecentVersion")
#Query(nativeQuery=true,
countQuery="""
SELECT COUNT(1)
FROM
(
SELECT
ROW_NUMBER() OVER (
PARTITION BY name, provider_id, state
ORDER BY version DESC) version_partition,
*
FROM mydb.mytable
WHERE
(name ILIKE ('%' || :name || '%') OR (:name = '')) AND
(namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
(state = :state OR (:state = ''))
) t
WHERE version_partition = 1
""",
value="""
SELECT id, version, state, name, internal_name, namespace, provider_id, config, create_date, update_date
FROM
(
SELECT
ROW_NUMBER() OVER (
PARTITION BY name, provider_id, state
ORDER BY version DESC) version_partition,
*
FROM mydb.mytable
WHERE
(name ILIKE ('%' || :name || '%') OR (:name = '')) AND
(namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
(state = :state OR (:state = ''))
) t
WHERE version_partition = 1
/*#{#pageable}*/
""")
public Page<Entity> findByNamespaceContainsAndNameContainsAndRawStateContainsMostRecentVersion(#Param("namespace")String namespace, #Param("name")String name, #Param("state")String state, Pageable pageable)
The key here was to use: /*#{#pageable}*/
It allows me to do sorting and pagination.
You can test it by using something like this: http://localhost:8080/api/v1/entities/search/namespaceAndNameAndRawStateContainsMostRecentVersion?namespace=&name=&state=published&page=0&size=3&sort=name,desc
Watch out for this issue: Spring Pageable does not translate #Column name
Create your custom repository:
public interface ProductsCustomRepository extends JpaRepository<ProductResultEntity, Long> {
#Query(
value = "select tableA.id, tableB.bank_name from tableA join tableB on tableA.id = tableB.a_id where tableA.id = :id
and (:fieldX is null or tableA.fieldX LIKE :fieldX)",
countQuery = "select count(*) from tableA join tableB on tableA.id = tableB.a_id where tableA.id = :id
and (:fieldX is null or tableA.fieldX LIKE :fieldX)",
nativeQuery = true
)
Page<ProductResultEntity> search(#Param("id") Long aId,
#Param("fieldX") String keyword, Pageable pageable
);
}
Create View as query of:
create view zzz as select * from tableA join tableB on tableA.id = tableB.a_id
Generate ProductResultEntity from that zzz view (and delete view zzz when have done)
Test call function and enjoy it:
productsRepository.search("123", "%BANK%", PageRequest.of(0, 5, Sort.by(Sort.Direction.ASC, "id")));
Entity:
#Entity
public class ProductResultEntity {
private Long id;
private String bank;
#Id
#Column(name = "id", nullable = false)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "bank_name", nullable = false)
public String getBank() {
return bank;
}
public void setBank(String bank) {
this.bank = bank;
}
}
It does work as below:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "select * from (select (#rowid\\:=#rowid+1) as RN, u.* from USERS u, (SELECT #rowid\\:=0) as init where LASTNAME = ?1) as total"+
"where RN between ?#{#pageable.offset-1} and ?#{#pageable.offset + #pageable.pageSize}",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
For me below worked in MS SQL
#Query(value="SELECT * FROM ABC r where r.type in :type ORDER BY RAND() \n-- #pageable\n ",nativeQuery = true)
List<ABC> findByBinUseFAndRgtnType(#Param("type") List<Byte>type,Pageable pageable);
I'm using the code below. working
#Query(value = "select * from user usr" +
"left join apl apl on usr.user_id = apl.id" +
"left join lang on lang.role_id = usr.role_id" +
"where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds ORDER BY ?#{#pageable}",
countQuery = "select count(*) from user usr" +
"left join apl apl on usr.user_id = apl.id" +
"left join lang on lang.role_id = usr.role_id" +
"where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds",
nativeQuery = true)
Page<AplUserEntity> searchUser(#Param("scrname") String scrname,#Param("uname") String uname,#Param("roleIds") List<Long> roleIds,Pageable pageable);
Removing \n#pageable\n from both query and count query worked for me.
Springboot version : 2.1.5.RELEASE
DB : Mysql
You can use below code for h2 and MySQl
#Query(value = "SELECT req.CREATED_AT createdAt, req.CREATED_BY createdBy,req.APP_ID appId,req.NOTE_ID noteId,req.MODEL model FROM SUMBITED_REQUESTS req inner join NOTE note where req.NOTE_ID=note.ID and note.CREATED_BY= :userId "
,
countQuery = "SELECT count(*) FROM SUMBITED_REQUESTS req inner join NOTE note WHERE req.NOTE_ID=note.ID and note.CREATED_BY=:userId",
nativeQuery = true)
Page<UserRequestsDataMapper> getAllRequestForCreator(#Param("userId") String userId,Pageable pageable);
You can achieve it by using following code,
#Query(value = "SELECT * FROM users u WHERE ORDER BY ?#{#pageable}", nativeQuery = true)
List<User> getUsers(String name, Pageable pageable);
Simply use ORDER BY ?#{#pageable} and pass page request to your method.
Enjoy!
#Query(value = "select " +
//"row_number() over (order by ba.order_num asc) as id, " +
"row_number() over () as id, " +
"count(ba.order_num),sum(ba.order_qty) as sumqty, " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name, " +
"from biz_arrangement ba " +
"left join mst_dpp md on ba.dpp_code = md.dpp_code " +
"where 1 = 1 " +
"AND (:#{#flilter.customerCodeListCheck}='' OR ba.customer_code IN (:#{#flilter.customerCodeList})) " +
"AND (:#{#flilter.customerNameListCheck}='' OR ba.customer_name IN (:#{#flilter.customerNameList})) " +
"group by " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name ",
countQuery = "select " +
"count ( " +
"distinct ( " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name) " +
")" +
"from biz_arrangement ba " +
"left join mst_dpp md on ba.dpp_code = md.dpp_code " +
"where 1 = 1 " +
"AND (:#{#flilter.customerCodeListCheck}='' OR ba.customer_code IN (:#{#flilter.customerCodeList})) " +
"AND (:#{#flilter.customerNameListCheck}='' OR ba.customer_name IN (:#{#flilter.customerNameList})) ",
nativeQuery = true)
Page<Map<String, Object>> nativeQueryDynamicPageAndSort(#Param("flilter") Flilter flilter, Pageable pageable);
no need to add ?#{#pageable},
the problem I got is when I use
row_number() over (order by ba.order_num asc) as id,
the input sort won't work
when I change to
row_number() over () as id,
the dynamic input sort and pagination are both okay!
This is a group by query with a row id.
Replacing /#pageable/ with ?#{#pageable} allow to do pagination.
Adding PageableDefault allow you to set size of page Elements.

org.hibernate.hql.internal.ast.QuerySyntaxException: writes is not mapped

I set up a Database Application with Spring an Hibernate and I'm using a Many-To-Many-Relationship.
Here's the code:
Author.java
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(name = "writes", joinColumns = {#JoinColumn(name = "authorId")}, inverseJoinColumns = {#JoinColumn(name = "publicationId")})
private Set<Publication> publications = new HashSet<Publication>();
Publication.java
#ManyToMany(mappedBy = "publications")
private Set<Author> authors = new HashSet<Author>();
these lines of code generate a connection-table named writes, but when I try to run a query over all Tables int gives me the error, named above.
this is the method, that schould run the query:
#Transactional
public List<Author> findAuthorByLastname(String lastName) {
String hql = "from Author a, Publication p, writes w where a.id = w.authorId and p.id = w.publicationId and a.lastname = :lastName";
Query q = sessionFactory.getCurrentSession().createQuery(hql);
q.setParameter("lastName", lastName);
List<Author> result = q.list();
return result;
}
You don't need to mention connection table explicitly in HQL queries (moreover, you even cannot mention them - only mapped entities). You need to use join on mapped relationships instead.
Also, it's not quite clear what you want to achieve.
If you want to fetch Authors with eagerly filled collections of their Publications in one query, use join fetch:
select distinct(a) from Author a join fetch a.publications where a.lastName = :lastName
If you want to fetch a list of pairs (Author, Publication), use regular join:
select a, p from Author a join a.publications p where a.lastName = :lastName

Resources