Couchbase view for document deletion - java

I'm using couchbase server with spring data. Also for the crud operations I'm using spring org.springframework.data.repository.CrudRepository. I want to remove User documents which have same domain name. domain is a attribute of User pojo. I was able to fetch the documents based on the domain attribute value.
This is the my repo class.
public interface UserRepository extends CrudRepository<User, String>{
List<User> findByDomain(Query query);
void deleteByDomain(Query query);
}
Also the view for findByDomain is,
function (doc, meta) {
if (doc._class == "com.link.pojo.User") {
emit(doc.domain, null);
}
}
This is working for get all documents in same domain name. So I used the same view for deleteByDomain() function. It gives me an error.Seems like this view only work for fetch data. How can I remove documents which in same domain? Thanks.
org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.util.ArrayList<?> to type void for value '[com.link.pojo.User#21dfd606, com.link.pojo.User#6e5c3549, com.link.pojo.User#67ae8439, com.link.pojo.User#726aef5c]';
nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type void
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176)
at org.springframework.data.repository.core.support.QueryExecutionResultHandler.postProcessInvocationResult(QueryExecutionResultHandler.java:75)

Your view needs to emit the object ID for each object in the view. Then take that array of IDs and for each one, call a delete on each of those IDs. If it fits your use case, a better way and should reduce the load on your cluster if there are a lot to delete is to set a random TTL between now and X hours/days/whatever on each object to be deleted. Then the Couchbase server will delete them as they are expired in a staggered fashion. If you need them deleted as soon as possible, then obviously use the delete call on the object IDs.

Related

How to get Data from REDIS in Spring Boot based on multiple parameter in where clause like we get in JPA as findByIdAndName

I have a requirement where I need to replace mysql with Redis, so I have method for mysql in JPA as findByIdAndName.
And in Redis I am storing key and Object like <Integer,Employee> (Employee is a class and Integer is Id ) so If I want to get employee object from redis based on Integer-Id I can easily get those with findById mentioned below but what if I want to get data based on Employee Name and age so any Idea how to use hashOperation in that way or how to store data in redis in way so that I can get the desired result.
For Example in RedisImplementation:
public Employee findById(Integer id) {
Employee emp = redisTemplate.opsForHash().get("EMPLOYEE_HASH",Id);
}
I want to add a method which can get data based on ID and Name like findByIdAndName
You should use #Cacheable as it enables you to define key with EL expressions.
An example is the following :
#Cacheable(value = "items", key = "#id")
public Item getItem(Integer id) {
Item item = itemRepository.findById(id).orElseThrow(RuntimeException::new);
logger.info("Loading data from DB {}", item);
return item;
}
I am pretty sure #Cacheable supports composite keys like POJOS instead of primitives as keys. Also if you do not specify key explicitly it will take the arguments of the method that has the annotation as a key.
A really good documentation / tutorial is the following one https://springhow.com/spring-boot-redis-cache/
Hope I helped :)

How to get only specified object class from mongo collection with spring data

I write two classes in one mongo collection, say One and Two. In these classes I have field someId. Then I want to get all One objects with specified someId. I created a method:
Page<One> findBySomeId(String id, Pageable pageable);
But get error:
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate ...
As I see, mongo take both One and Two objects, and then trying to create One objects from them.
I tried write next:
Page<One> findOneBySomeId(String id, Pageable pageable);
and got the same error. How to write a proper method to retrieve only specified objects from mongo DB with spring data?
Your query should be like this
Page<IOne> findByOneSomeId(String id, Pageable pageable);
public interface IOne {
public One getOne();
}
You should limit the query by specifying something that distinguishes One and Two. For example, you can filter by:
the (internal) _type field that spring automatically persist, which is equal to the fully qualified class name (unless #TypeAlias is provided, when it could be whatever you set)
some other property that you know is present only in the One documents (Page<One> findBySomeIdAndPropertyExistsTrue(String id, Pageable pageable))
With Spring Data you can use following syntax :
One findFirstBySomeId(String someId);
Here is documentation about spring data(4.4.5. Limiting Query Results) where you find the explanation and examples: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference

How to update only a subset of fields and update the repository?

I'm making a spring boot application, and I'm looking to update an existing entry in the DB through my service and controller. In my service layer I have the below method. So I'm retrieving the fields associated with a caseID, creating a model mapper which maps my entity object class to my VO, and then mapping the retrieved data to my DTO. Then I save my repository. The purpose is to add only the fields which I have specified in my req message ie if I only want to update 1 field out of 20, it updates this field and leaves the rest untouched. The below runs successfully, but the field I specify in my request message in postman does not update in the DB. Why is this? I have tried mapping different objects and saving different variables to the repository but nothing seems to update the DB.
public StoredOutboundErrorCaseVO updateCase(OutboundErrorCaseVO outboundErrorCaseVO, Long caseNumber) {
OutboundErrorCaseData existingCaseData = ErrorCaseDataRepository.findById(caseNumber).get();
ModelMapper mm = new ModelMapper();
mm.getConfiguration().setAmbiguityIgnored(true);
OutboundErrorCaseData uiOutboundErrorCaseData = mm.map(outboundErrorCaseVO,
OutboundErrorCaseData.class);
mm.map(existingCaseData, uiOutboundErrorCaseData);
ErrorCaseDataRepository.save(uiOutboundErrorCaseData);
return mm.map(uiOutboundErrorCaseData, StoredOutboundErrorCaseVO.class);
}
Controller - code omitted for brevity, POST method (I usually use PUT for updates but I believe I can still use POST)
StoredOutboundErrorCaseVO updatedCase = outboundErrorService.updateCase(outboundErrorCaseVO,
caseNumber);
Repo
#Repository
public interface OutboundErrorCaseDataRepository extends JpaRepository<OutboundErrorCaseData, Long> {
You are getting data and passing it into existingCaseData and save uiOutboundErrorCaseData. So my guess is Hibernate is adding a new object into the database with new Id and with you updated value. It of course depends on your model definition. Especially id.
I also think Hibernate won't let you save uiOutboundErrorCaseData with the same Id if you already have an object in Hibernate Session associated with that id. So, why don't you update existingCaseData with the new value and save it back.
I created a working solution, although I realise it can be improved, it certainly works. The only drawback is that I need to specify all the fields which can be updated, ideally I want a solution which takes in n number of fields and updates the record.
OutboundErrorCaseData existingCaseDta = ErrorCaseDataRepository.findById(caseNumber).get();
if (outboundErrorCaseVO.getChannel() != null) {
existingCaseDta.setChannel(outboundErrorCaseVO.getChannel());
}
ErrorCaseDataRepository.save(existingCaseDta);
ModelMapper mm = new ModelMapper();
return mm.map(existingCaseDta, StoredOutboundErrorCaseVO.class);

How to convert type from ObjectId to Long when using MongoTemplate?

Normally when using spring data repositories, an object in which the result data can be stored is needed like the customer in this example: https://spring.io/guides/gs/accessing-data-mongodb/ .
In my case I'm trying to use an object which is declared in another project I'm importing using maven - let's call it MyDoc. The object has an attribute Long id while the document in the MongoDB has an addition field _id from type ObjectId. This btw is like this because the MongoDB serves as an archive and the actual id from MyDoc would not be unique.
In a service class I then use this the MongoTemplate to make database queries like this:
List<MyDoc> list = template.findAll(MyDoc.class, "DOCS");
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.bson.types.ObjectId] to type [java.lang.Long]
How can I convert the ObjectId to a type of Long?
Alternately, I could, of course, use the java MongoDB driver but I wanted to reduce the number of dependencies to maintain since the MongoDB driver comes with the boot-starter-data-MongoDB dependency, and also hoped for a more intuitive way, in the end, to interact with the database like with the spring data repositories.
First thing is Long Id from MyDoc is not unique, so it cannot act as _id of mongoDB.
Then you need to have one more _id field in your class. By Default Spring data mongoDB will map field named id to _id in dataBase.
Essentially what you can do is create a wrapper class around MyDoc by extending it and then add new field of Type ObjectId and annotate it with #Id. By that way you will have unique index and also mongoTemplate will not try to convert _id of database to Long id

spring data inheritance for repository reuse

I am using Spring Data to load an object and all works well...However, I don't want to load the entire object as I am returning a list to display in a table, so I only want to load what is in the table. then, when a user selects "details" I want to make an AJAX call to the server to load the entire object. My thought was to have a Base Class "TableView" then to have a subclass "Class DetailsView extends TableView". I could probably create a new repository, so one for the TableView and one for the DetailsView, but I'm wondering if there is a way to use the same repository class? below is an example of what I'd like to do, but I'm not sure how to change the repositoryClass to achieve what I want...I get the following error:
SQLGrammarException: could not extract ResultSet at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:261)
class TableView{
String title;
}
class DetailsView extends TableView{
String details;
}
interface ITableViewRepository extends CrudRepository<TableView, Integer>{
You can write two queries in your TableViewRepository.
One for returning id and title from you object
#Query("SELECT tv.id, tv.title FROM TableView tv")
TableView findWithTitles();
And after that just call a method findOne with TableView id to return entire object.

Categories

Resources