Ignite CrudRepository still getting name conflict for deleteAll - spring-boot

I using ignite core, and ignite-spring-data both 2.7.0
compile "org.apache.ignite:ignite-core:2.7.0"
compile "org.apache.ignite:ignite-spring-data:2.7.0"
compile('org.springframework.boot:spring-boot-starter-jdbc:2.1.5.RELEASE');
But I still get this error:
error: name clash: deleteAll(Iterable<? extends T>) in CrudRepository and deleteAll(Iterable<ID>) in IgniteRepository have the same erasure, yet neither overrides the other
where T,ID are type-variables:
T extends Object declared in interface CrudRepository
ID extends Serializable declared in interface IgniteRepository
According to https://issues.apache.org/jira/browse/IGNITE-6879 this issue was resolved with version 2.7.0 so why am I still getting it?
if I use instead:
compile "org.apache.ignite:ignite-spring-data_2.0:2.7.0"
It seems to break everything, so I am not sure that an option.
import org.apache.ignite.springdata.repository.IgniteRepository;
import org.apache.ignite.springdata.repository.config.Query;
import org.apache.ignite.springdata.repository.config.RepositoryConfig;
#RepositoryConfig(cacheName = "PersonCache")
public interface PersonRepository extends IgniteRepository<Person, Long> {
List<Person> findByFirstNameAndLastName(String firstName, String lastName);
#Query("SELECT c.* FROM Person p JOIN \"ContactCache\".Contact c ON p.id=c.personId WHERE p.firstName=? and p.lastName=?")
List<Contact> selectContacts(String firstName, String lastName);
#Query("SELECT p.id, p.firstName, p.lastName, c.id, c.type, c.location FROM Person p JOIN \"ContactCache\".Contact c ON p.id=c.personId WHERE p.firstName=? and p.lastName=?")
List<List<?>> selectContacts2(String firstName, String lastName);
}

Just switch to new 2.0 support version of ignite spring data.
compile "org.apache.ignite:ignite-spring-data_2.0:${igniteVersion}"
import org.apache.ignite.springdata20.repository.IgniteRepository;
import org.apache.ignite.springdata20.repository.config.Query;
import org.apache.ignite.springdata20.repository.config.RepositoryConfig;
No worries!

After changing to use:
<dependency>
<groupId>org.apache.ignite</groupId>
<artifactId>ignite-spring-data_2.0</artifactId>
<version>${ignite.version}</version>
</dependency>
.....
<ignite.version>2.7.0</ignite.version>
You will have to re-import everything. so just delete the 'import' part from the code all together. Since now the IgniteRepository etc are coming from a package called org.apache.ignite.springdata20.repository .... instead of the old one.

Related

Spring Boot #Query annotation throwing unexpected token error on the alias

Below is the snippet of the offending code
package com.example.demo.repositories;
import com.example.demo.models.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
#Query("SELECT s FROM Student WHERE s.email = ?1")
Optional<Student> findStudentByEmail(String email);
}
This a piece of the error returned
caused by: org.hibernate.QueryException: Unable to resolve path [s.email], unexpected token [s]...
You missed alias(in your case 's') with the entity name.
so it should be,
#Query("SELECT s FROM Student s WHERE s.email = ?1")
Optional<Student> findStudentByEmail(String email);
#Query("SELECT s FROM Student s WHERE s.email = ?1")
Optional<Student> findStudentByEmail(String email);
There are two ways to do it
As already outlined in the other answers, you missed declaring the alias in the statement. Thus the correct code should be
#Query("SELECT s FROM Student s WHERE s.email = ?1")
Optional<Student> findStudentByEmail(String email);
Alternatively, if your query is simple as the one above, you can try omitting the alias as shown in the below example
#Query("FROM Student WHERE email = ?1")
Optional<Student> findStudentByEmail(String email);

Why is Spring Cassandra not using the Values set in #Table with Scala?

I have the following code...
#Table(keyspace = "ks", name="otherThing" )
class Thing extends Serializable{
...
}
However when I run...
repo.findAll()
I get an error that looks like it isn't using the values I provided...
Query; CQL [SELECT * FROM Thing;]; unconfigured table Thing
I would expect
Select * from ks.otherThing;
What am I missing?
Update
I tried converting to the following Pojo
import com.datastax.driver.mapping.annotations.Table;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
#Table( keyspace="ks", name="otherThing" )
public class Thing implements Serializable {
...
}
And my repo is pretty simple...
import org.springframework.stereotype.Repository;
#Repository
public interface ThingRepository extends CassandraRepository<Thing, ThingId> { }
but
thingRepo.findAll();
gives...
Query; CQL [SELECT * FROM thing;]; unconfigured table thing
So the mistake I made was trying to do this with a connection that was set up using my company's spring autoconfig. This allowed me to configure the connection via application.properties. I noticed that the keyspace was previously declared there so I went back and changed my domain object to...
import org.springframework.data.cassandra.core.mapping.Table
#Table("otherThing" )
class Thing extends Serializable{
...
}
Now it is working. Leaving this answer up in case others get confused.

Getting aggregate data from table

I want to get aggregate data from a table using spring data.
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryEntity> getSummary(#Param("groupId" Long groupId));
package com.refinitiv.eit.kv.label.enity.response;
import lombok.AllArgsConstructor;
import lombok.Data;
#Data
#AllArgsConstructor
public class SummaryResponse {
#Column("TOTAL_1")
private Double total_1;
#Column("MAX_1")
private Double max_1;
}
However I get this error : "Could not read property #org.springframework.data.annotation.Id() " ...
There should be no ID, only a single row with the summary data.
Any ideas on getting the summary data?
(the code is more complex but cleared up for this)
First of all, if you need your entity SummaryResponse to be managed by JPA and eventually persist it, you need to annotate it as #Entity and assign it either id or composite id (annotated with #Id).
If you just want to use that DTO for fetching the data, you can use a Spring's interface based projection for that:
public interface SummaryResponseProjection{
getTotal1();
getMax1();
}
and then use it for mapping the results of the query:
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryResponseProjection> getSummary(#Param("groupId" Long groupId));
Found the reason:
This method was part of a repository defined as ReactiveCrudRepository<RawEntity, Long>, with RawEntity having the id defined.
Moving the method into a new repo defined as ReactiveCrudRepository<SummaryEntity, Void> solves the issue.
Thanks all!

How to use projection interfaces with pagination in Spring Data JPA?

I'm trying to get a page of a partial entity (NetworkSimple) using the new feature of spring data, projections
I've checked the documentation and if I request only:
Collection<NetworkSimple> findAllProjectedBy();
It works, but if I'm using pageable:
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
It throws an error:
org.hibernate.jpa.criteria.expression.function.AggregationFunction$COUNT cannot be cast to org.hibernate.jpa.criteria.expression.CompoundSelectionImpl
Any one has already work with this ?
My NetworkSimple class is the following:
public interface NetworkSimple {
Long getId();
String getNetworkName();
Boolean getIsActive();
}
Note: This feature should work in the way described by the original poster but due to this bug it didn't. The bug has been fixed for the Hopper SR2 release, if you're stuck on an earlier version then the workaround below will work.
It is possible to use Pageable with the new query projection features introduced in Spring Data JPA 1.10 (Hopper). You will need to use the #Query annotation and manually write a query for the fields you require, they must also be aliased using AS to allow Spring Data to figure out how to project the results. There is a good example in spring-boot-samples part of the spring boot repository.
In your example it would be quite simple:
#Query("SELECT n.id AS id, n.name AS networkName, n.active AS isActive FROM Network n")
Page<NetworkSimple> findAllProjectedBy(Pageable pageable);
I have made the assumption that your entity looks something like this:
#Entity
public class Network
{
#Id
#GeneratedValue
private Long id;
#Column
private String name;
#Column
private boolean active;
...
}
Spring Data will derive a count query automatically for the paging information. It is also possible to make use of joins in the query to fetch associations and then summarise them in the projection.
I think you need create findAllProjectedBy() as specification.Then you can use findAll() method like this.
example :findAll(findAllProjectedBy(),pageable)
Following link may be help to find how to create specification in spring.
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
The issue may come from the method name. The by keyword means that you ae filterig data by a specific property: findByName for example. Its called query creation from method name:
http://docs.spring.io/spring-data/jpa/docs/1.10.1.RELEASE/reference/html/#repositories.query-methods.query-creation
So try with Page<NetworkSimple> findAll(Pageable pageable);
Even with spring-data-jpa 1.11.4, something like
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAll(Pageable pageable);
}
would not compile; reporting
findAll(org.springframework.data.domain.Pageable) in NetworkRepository clashes with findAll(org.springframework.data.domain.Pageable) in org.springframework.data.repository.PagingAndSortingRepository
return type org.springframework.data.domain.Page<NetworkSimple> is not compatible with org.springframework.data.domain.Page<Network>
The workaround we found was to rename findAll to findAllBy, e.g.
public interface NetworkRepository extends JpaRepository<Network, String> {
Page<NetworkSimple> findAllBy(Pageable pageable);
}
You can use interface projection with Pageable like this :
Page<NetworkSimple> findPagedProjectedBy(Pageable pageable);
with some parameter :
Page<NetworkSimple> findPagedProjectedByName(String name, Pageable pageable);
Implementing interface projection with pagination
1. Our ResourceEntity.java class
#Getter
#Setter
#NoArgsConstructor
#Entity
public class ResourceEntity{
private Long id;
private String name;
}
2. Creating projection Interface name ProjectedResource.java, which maps data collected by the SQL query from repository layer method
public interface ProjectedResource {
Long getId();
String getName();
String getAnotherProperty();
}
3. Creating Repository layer method: getProjectedResources()
We are considering the database table name is resource.
We are only fetching id and name here.
#Query(name="select id, name, anotherProperty from resource", countQuery="select count(*) from resource", nativeQuery=true)
Page<ProjectedResource> getProjectedResources(Pageable page);
Hope the issue will be resolved!
You can use:
#Query("SELECT n FROM Network n")
Page<? extends NetworkSimple> findAllProjectedBy(Pageable pageable);

#NamedQuery override findAll in Spring Data Rest JpaRepository

Is there a way to override the findAll query executed by Spring Data Rest?
I need a way of filtering the results based on some specific criteria and it seems that using a #NamedQuery should be along the lines of what I'm looking for so I setup a test.
#Entity
#Table(name = "users")
#NamedQueries({
#NamedQuery(name = "User.findAll", query="SELECT u FROM User u WHERE u.username = 'test'"),
#NamedQuery(name = "User.findNameEqualsTest", query="SELECT u FROM User u WHERE u.username = 'test'")
})
public class User implements Serializable, Identifiable<Long> { }
With this in place I would expect SDR to utilize my findAll() query (returning 1 result) but instead it executes the same old findAll logic (returning all results).
In my Repository I added:
#Repository
#RestResource(path = "users", rel = "users")
public interface UserJpaRepository extends JpaRepository<User, Long> {
public Page<User> findNameEqualsTest(Pageable pageable);
}
and in this case it DOES pick up the provided #NamedQuery. So...
How should I go about overriding the default findAll() logic? I need to actually construct a complex set of criteria and apply it to the result set.
In the upcoming version 1.5 (an RC is available in our milestone repositories) of Spring Data JPA you can simply redeclare the method in your repository interface and annotate it with #Query so that the execution as query method is triggered. This will then cause the named query to be looked up just as you're already used to from query methods:
interface UserJpaRepository extends PagingAndSortingRepository<User, Long> {
#Query
List<User> findAll();
Page<User> findNameEqualsTest(Pageable pageable);
}
A few notes on your repository declaration:
You don't need to annotate the interface with #Repository. That annotation doesn't have any effect at all here.
Your #RestResource annotation configures the exporter in a way that will be the default anyway in Spring Data REST 2.0 (also in RC already). Ging forward, prefer #RestRepositoryResource, but as I said: the pluralization will be the default anyway.
We generally don't recommend to extend the store specific interfaces but rather use CrudRepository or PagingAndSortingRepository.
Yes, you can create your Implementation of your Repository interface, there is acouple section in
http://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/html/repositories.html#repositories.custom-implementations
Repository
#Repository
public interface PagLogRepository extends JpaRepository<PagLogEntity, Long>, PagLogCustomRepository {
Custom Interface
public interface PagLogCustomRepository {
PagLogEntity save(SalesForceForm salesForceForm) throws ResourceNotFoundException;
Custom implementation
public class PagLogRepositoryImpl implements PagLogCustomRepository {
#Override
public PagLogEntity save(final SalesForceForm salesForceForm) throws ResourceNotFoundException {
query = emEntityManager.createNamedQuery("findItemFileByDenormalizedSku", ItemFileEntity.class);
query.setParameter("skuValue", rawSku);
Instead of override save make it with findAll, then you can create complex customization

Resources