Spring JPA without hibernate - spring

I am not able to understand the below method in Spring -JPA.
#RepositoryRestResource
public interface TestRepository extends JpaRepository<Vehicle, BigInteger>{
public List<Vehicle> findAll(Sort sort);
}
Vehice is a entity or domainobject.
What does the method findAll(Sort sort) do.
Please help me.

This declare the method already in JpaRepository again.
List<T> JpaRepository.findAll(Sort sort);
with T = Vehicle take all vehicles form the database (or NOSQL store) with a the given sorting and returns them.
#RepositoryRestResource is a annotation to publish this as an HATEAOS rest resource.

It allows you to find all vehicles, sorted as specified by the Sort parameter.

Related

#EntityGraph annotation doesn't work properly?

I need to implement two different implementations for the same findAll() method by following different EntityGraphs annotations. By referencing through another StackOverflow post, I found a way to implement the same findAll() method with different EntityGrpahs. But when I use default methods as mentioned in that post, I am not getting the expected behavior. It neglects the #EntityGraph annotation and returns lazy Collections by following the default behavior.
Please provide a fix for this issue or state any other better solution that I can implement to solve this problem.
public interface BspCategoryRepository extends JpaRepository<DbpMetaBspCategory, String> {
#EntityGraph(attributePaths = {"dbpBspMetaCollection","dbpBspMetaCollection.dbpBspMetaCustomFieldCollection","dbpBspMetaCollection.bspType","dbpBspMetaCollection.bankCode","dbpBspMetaCollection.dbpBspMetaCustomFieldCollection.fieldType"}, type = EntityGraph.EntityGraphType.FETCH)
default List<DbpMetaBspCategory> findAllCategories(){
return findAll();
}
}
Please refer to the second answer in the post which was answered by Femi.
References
Spring Data simply can not know about this annotation, as the method is not abstract. You should be able to declare the method just like this:
#EntityGraph(attributePaths = {"dbpBspMetaCollection","dbpBspMetaCollection.dbpBspMetaCustomFieldCollection","dbpBspMetaCollection.bspType","dbpBspMetaCollection.bankCode","dbpBspMetaCollection.dbpBspMetaCustomFieldCollection.fieldType"}, type = EntityGraph.EntityGraphType.FETCH)
List<DbpMetaBspCategory> findAllCategories();

Spring Mongo - set custom collection on entity implementing interfaces

Given a mongo entity class :
#Data
#Document(collection = "#{ T(de.axa.services.ecm.contentmanagement.service.archivbearbeiten.util.ServiceUtils).getMongoCollectionPreFix() }_allgarchiv")
public class AllgArchivReference implements Kleinsparte {
My aim is to store this entity in an collection "xxx_allgarchiv" whereby "xxx" is based on the runtime environment.
I have one Crud repository:
#Repository
public interface ReferenceRepository extends MongoRepository<Kleinsparte, String> {
}
and the simple implementation....
result = referenceRepository.save(kleinsparte);
No I want to store the AllgArchivReference in the collection above ("xxx_allgarchiv").
Unfortunately the entity is stored in a new created collection "kleinsparte" but this is not what i want.
How could I enforce spring data to store allgarchivReference in eponymous collection without creating a new own crud repository?
By the way, there more than 20 other Reference-Entities which are also implementing the interface "Kleinsparte" and i don't want to create for each entity an own crud repository interface.
Is this possible? Any help are really appreciate.
Kind regards,
Bodo

Spring Data - Build where clause at runtime

In Spring Data, how can I append more conditions to an existing query?
For example, I have the CrudRepository below:
#RepositoryRestResource
public interface MyRep extends CrudRepository<MyObject, Long> {
#Query("from MyObject mo where mo.attrib1 = :attrib1")
List<MyObj> findMyObjects(String attrib1, String conditions);
}
At runtime, I will need to call "findMyObjects" with two params. The first param is obviously the value of attrib1. the second param will be a where clause that would be determined at runtime, for example "attrib2 like '%xx%' and attrib3 between 'that' and 'this' and ...". I know this extra where condition will be valid, but I don't know what attributes and conditions will be in it. Is there anyway to append this where clause to the query defined in the #Query annotation?
Unfortunately, no. There is no straightforward way to achieve that.
You'll want to use custom reporistory methods where you'll be able to inject an EntityManager and interact with EntityManager.createQuery(...) directly.
Alternatively, you can build dynamic queries using Specifications or QueryDsl.
I ended up injecting an EntityManager that I obtained in the rest controller. Posting what I did here for criticism:
The repository code:
#RepositoryRestResource
public interface MyRepo extends CrudRepository<MyObject, Long> {
default List<MyObject> findByRuntimeConditions(EntityManager em, String runtimeConditions) {
String mySql = "<built my sql here. Watch for sql injection.>";
List<MyObject> list = em.createQuery(mySql).getResultList();
return list
}
}
The Rest controller code:
#RestController
public class DataController {
#Autowired
EntityManager em;
// of course watch for sql injection
#RequestMapping("myobjects/{runtimeConditions}")
public List<MyObject> getMyObjects(#PathVariable String runtimeConditions) {
List<MyObject> list = MyRepo.findByRuntimeConditions(em, runtimeConditions);
return list;
}
}

How to create custom abstract repository like PagingAndSortingRepository, etc?

For example in my persistence:
public interface SomePersistence extends JpaRepository<SomeClass, String> {};
I can write method like:
#Query("some query")
List<SomeClass> getAllWithSomeParam();
and spring knows to use SimpleJpaRepository class - implementation of JpaRepository.
When i write:
#Query("some query")
Page<SomeClass> getAllWithSomeParam(Pageable page);
spring knows to use implementation of PagingAndSortingRepository.
But now i want to add my own returned type - Cursor<T>
It`s mean i want write:
#Query("some query")
Cursor<SomeClass> anyMethodName();
Then i want to give spring my own repository CursorRepository with its personal CursorRepositoryImpl when i have only one method Cursor<T> findAll()
Can i realize it?

Return custom-typed object from JpaRepository

I have the following repository:
public interface UserRepository extends BaseDAO<User> {
Collection<User> findByEmail(#Param("email") String email);
#Query("select new com.data.CustomUser(upper(substring(u.lastName, 1, 1)) as initial, count(*)) from User u join u.chats c where c.business=:business group by upper(substring(u.lastName, 1, 1)) order by initial")
List<CustomUser> getContactsIndex(#Param("email") String email);
}
which is exposed with Spring Data REST. The User object is a managed entity, while CustomUser not and as you can see, it's build on-fly by using custom query.
Once I want to call that function, it fails with Persistent entity must not be a null! exception. Is there any way to implement this behavior?
P.S. Expose CustomUser with separate repository is impossible because it is not a managed entity.
One challenge with using Spring Data Rest is when you hit an edge case and you don't know whether you've hit a bug or whether you're just outside the scope of what the library is intended for. In this case I think you are at the edge of what SDR will easily do for you, and it's time to implement your own controller.
Spring Data Rest is looking for an Entity - in your case a User - as the return type for ALL methods in the repository to expose under /entities/search, and breaks when it doesn't find that entity type. The User it wants to serialize isn't there, hence the "Persistent entity must not be null".
The way around this is to write a simple #Controller that has a #RequestMapping for the exact same url exposed by the repository method. This will override the SDR generated implementation for that url, and from that you can return whatever you want.
Your implementation might look something like this:
#Controller
public class CustomUserController {
private final UserRepository repository;
#Inject
public CustomUserController(UserRepository repo) {
repository = repo;
}
#RequestMapping(value = "/users/search/getContactsIndex", method = GET, produces = {MediaType.APPLICATION_JSON_VALUE})
public #ResponseBody List<CustomUser> getContactsIndex(#RequestParam String email) {
return repository.getContactsIndex(email);
}
}
Be aware that there is a "recommended" way to override functionality this way. There is an open issue to document the best way to do this.

Resources