Rest api via spring - java

I have to get all data from MySQL in a table using condition select query where fields is isdeleted=0, location=1. How could I implement this in repository and access manager.
public interface FoodCourtRepository extends JpaRepository<FoodCourtEntity, Long> {
List<FoodcaseEntity> findByIsdeleted(Boolean isDeleted);
}
In access manager
public List<FoodcaseDO> getAllFoodCourt() {
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeleted(false);
}

You need to add another condition as well, for location, e.g.:
public List<FoodcaseEntity> findByIsdeletedAndLocation(boolean deleted, int location);
And call it with false and 1 as arguments, e.g.:
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeletedAndLocation(false, 1);
This should give you the required result.
Updte
If you want to fetch the data for multiple locations then you need to write a method that supports IN, e.g.:
public List<FoodcaseEntity> findByIsdeletedAndLocationIn(boolean deleted, List<Integer> location);
And then call it like this:
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeletedAndLocation(false, Arrays.asList(2,3,4,5));

JPA provides #Query to write custom query. You can define another interface called FoodCourtRepositoryCustom and write custom query as below:
public interface FoodCourtRepositoryCustom {
#Query("SELECT fe FROM FoodcaseEntity fe WHERE fe.isdeleted=?1 AND fe.location=?2 ")
List<FoodcaseEntity> findByIsdeletedAndLocation(Boolean isDeleted, Integer location);
}
Then extends this interface in your repository inteface as below:
public interface FoodCourtRepository extends JpaRepository<FoodCourtEntity, Long>, FoodCourtRepositoryCustom{
List<FoodcaseEntity> findByIsdeleted(Boolean isDeleted);
}
Now method is available in your access manager.
public List<FoodcaseDO> getAllFoodCourt() {
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeleted(false);
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeletedAndLocation(false, 1);
}

In a repository class add,
List<FoodcaseEntity> foodCaseList = foodcourtRepository.findByIsdeletedAndLocation(boolean isSelected,int location);
then u can send selected and location values.it will return list of values based on condition.

Related

Spring data jpa, how to filter and then sort results in this example?

I wrote a method, but as you can see - Category here is never used.
Is to possible to find only Dishes where Category is same as defined and only after it - sort it by parameter using plain Spring data jpa?
Or the only way to it is a custom query?
public List<Dish> findAllDishesSorted(String sortField, String sortDirection, String category) {
Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
? Sort.by(sortField).ascending() : Sort.by(sortField).descending();
return dishRepository.findAll(sort);
}
You could add a method like below to your DishRepository and it should be able to achieve that without needing to write custom query with #Query() annotation
public interface DishRepository extends CrudRepository<Dish, Long> {
Dish findByCategory(String category, Sort sort);
}

How to add ROOM queries that take parameters and return data

I am trying to create a new room database query that takes a parameter and returns a list. All the documents I read and videos I watch only show me as far as the DAO query (which I have done) but what I cannot find is how to create the subsequent queries for repository and viewModel classes.
This is my DAO query;
#Query("SELECT * FROM member WHERE name = :reselectedPlayerName")
List<Member> getPlayersForReselection(String reselectedPlayerName);
I have successfully created a 'LiveData' query (for another task) which does not take any parameters, but I do NOT want a Livedata query this time and I cannot see how to create the query in the repository class.
The answer as always is generally simple!... but when you cannot see the wood for the trees....
If anybody wants more detail, I am happy to detail what I found and what I did but this is what I ended up doing;
(I know I said I didn't want to use LiveData but I did just for proving)
DAO
#Query("SELECT * FROM member WHERE name = :aStr")
LiveData<List<Member>> getPlayersForReselectionDb(String aStr);
REPOSITORY
public LiveData<List<Member>> getPlayersForReselectionDb(String aStr){
reselectedMembers = memberDAO.getPlayersForReselectionDb(aStr);
return reselectedMembers;
}
VIEWMODEL
public LiveData<List<Member>> getPlayersForReselectionDb(String aStr) {
reselectedMembers = memberRepository.getPlayersForReselectionDb(aStr);
return reselectedMembers;
}
FRAGMENT
MemberViewModel memberViewModel = new
ViewModelProvider(this).get(MemberViewModel.class);
memberViewModel.getPlayersForReselectionDb("Fred Bloggs").observe(this,
new Observer<List<Member>>() {
#Override
public void onChanged(List<Member> members) {`enter code here`}
}
});

Why does not delete method of spring data (JPA) have any return values?

I have used a delete method of Spring Data JPA in the service layer, but I wonder why neither the deleteById method nor delete method has any return values.
If we inspect the implementation of the delete method carefully, there is an if statement that when the entity to be deleted doesn't exist returns nothing.
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null!");
if (entityInformation.isNew(entity)) {
return;
}
Class<?> type = ProxyUtils.getUserClass(entity);
T existing = (T) em.find(type, entityInformation.getId(entity));
// if the entity to be deleted doesn't exist, delete is a NOOP
if (existing == null) {
return;
}
em.remove(em.contains(entity) ? entity : em.merge(entity));
}
Personally, I think returning a Boolean value could be an adequate approach in this case because the controller layer will know about the deletion status, and the view layer can be provided with the far more reliable alert message.
Spring Data JPA design some build-in methods that way they think and give us the option to use the other way also.
You can easily get deleted records and their count using derived delete query supported By Spring Data JPA (Reference)
#Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
Fruit deleteById(Long id); // To get deleted record
}
#Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
Long deleteById(Long id); // To get deleted record count
}
use #Modifying and #Query ant it will return number of deleted rows.
#Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
#Modifying
#Query(value = "DELETE FROM Fruit f where f.id = ?1")
int costumDeleteById(Long id);
}
Another option would be to follow the suggestion from this answer and check if the number of affected entities is 1 (in case of a deleteById method).

How do I pass the type as a variable?

I'm working with DynamoDB. I want to create a db adapter class (rather than viewing a bunch of copy/pasted code in various sections of the program) that can do the following:
DynamoDBMapper mapper = Dynamo.getMapper(SomeClassHere.TABLE_NAME);
DynamoDBQueryExpression<SomeClassHere> queryExpression = new DynamoDBQueryExpression<SomeClassHere>()
.withHashKeyValues(passedInObjectHere);
List<SomeClassHere> list = mapper.query(SomeClassHere, queryExpression);
so SomeClassHere would be the name of a class as its Type and used for mapping fields in the DynamoDBMapper as well.
I'd like to pass in an object parameter similar to this:
public void getList(IDynamoDBModel model) {
DynamoDBMapper mapper = Dynamo.getMapper(GetTheClassTypeFromTheModel);
DynamoDBQueryExpression<GetTheClassTypeFromTheModel> queryExpression = new DynamoDBQueryExpression<GetTheClassTypeFromTheModel>()
.withHashKeyValues(model);
List<GetTheClassTypeFromTheModel> list = mapper.query(GetTheClassTypeFromTheModel, queryExpression);
}
This way, instead of copy/pasting 'code for save', 'code for delete', 'code for get item' everywhere, I can simply:
call a connection manager
get a connection to the DynamoDb from it
pass in the object with its preloaded values into the appropriate
method (save, delete, getItem, etc...)
I realize that generics are used at compile time and it may be a fruitless effort but I reeeeally want to clean up this inherited code base.
I am not familiar with DynomoDB.
But according to my understanding you want to implement generic data access layer from DynamoDB. it can be achieve via generic and I have implement below code you to understand how you can achieve this.
Please ignore DynamoDB specification and this code won't work by just copy and paste. so makes sure to edit accordingly.
Implement DynamoTypeProvider interface.
#FunctionalInterface
public interface DynamoTypeProvider<DynamoType> {
Class<DynamoType> getDynamoType();
}
Implement Generic Data access service for DyanamoDB as below.
public abstract class DynamoQueryService<DynamoType, DynamoDBModel extends DynamoTypeProvider<DynamoType>> {
public List<DynamoType> getList(DynamoDBModel model) {
DynamoDBMapper mapper = Dynamo.getMapper(model.getDynamoType());
DynamoDBQueryExpression<DynamoType> queryExpression = new DynamoDBQueryExpression<DynamoType>()
.withHashKeyValues(model);
return mapper.query(model.getDynamoType(), queryExpression);
}
}
Suppose Dynamo type is UserType and DynamoDBModel is User.
from User we should be able to get Dynamo DB type UserType.
public class UserType {
//your code.
}
public class User implements DynamoTypeProvider<UserType>{
//your code
#Override
public Class<UserType> getDynamoType() {
return UserType.class;
}
Then implement specify model type data access service. here it is UserDynamoQueryService.
public class UserDynamoQueryService extends DynamoQueryService<UserType, User> {
}
then you can get UserType as
UserDynamoQueryService service = new UserDynamoQueryService();
List<UserType> types = service.getList(new User());
Using Generic you can achieve this.
please makes sure edit this accordingly.
Or you can try below example.
public class DynamoQueryService {
public <T, X> List<T> getList(X x, Class<T> tClass) {
DynamoDBMapper mapper = Dynamo.getMapper(tClass);
DynamoDBQueryExpression<T> queryExpression = new DynamoDBQueryExpression<T>()
.withHashKeyValues(x);
return mapper.query(tClass, queryExpression);
}
}
And use as below.
DynamoQueryService queryService = new DynamoQueryService();
List<UserType> userTypes = service.getList(new User(), UserType.class);
Then User dose not need to implement DynamoTypeProvider.

Spring Data Rest: Query parameters chained with logical OR

I have an entity that is exposed by the following repository:
public interface InsertRepository extends PagingAndSortingRepository<InsertEntity, Long>, QueryDslPredicateExecutor<InsertEntity>, QueryDslBinderCustomizer<QInsertEntity> {
#Override
default void customize(QuerydslBindings bindings, QInsertEntity insert) {
bindings.bind(String.class).all(StringPath path, Collection<? extends String> values) -> {
BooleanBuilder predicate = new BooleanBuilder();
values.forEach(value -> predicate.or(path.containsIgnoreCase(value)));
return predicate;
});
}
}
What I'd like it to do is that all GET query parameters are chained as logical OR so that a query like ?description=searchText&customerName=searchText would execute an SQL query that looks as follows:
WHERE description LIKE '%searchText%' OR customerName LIKE '%searchText%'
However, I must be doing something wrong because it doesn't work - it is putting all query parameters into an AND query. That results in only those records being selected that contain searchText in customerName AND their description.
You can use named parameters such as
Example 53. Using named parameters
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
User findByLastnameOrFirstname(#Param("lastname") String lastname,
#Param("firstname") String firstname);
}
The answer provided by #kafkas is not accurate at all. There are quite few problems with it:
Annotation #Query is obsolette - Spring automatically does it for you, you just need to type the name of the method properly.
Annotations #Param are obsolette - Spring automatically takes parameters in given order, matched with those in method name.
You return single User entity, but you still use findBy instead of findOne - this leads to an error, if more than one record is found.
The last, but not least - provided method will not use LIKE comparation, but equals instead. You should use findByXXXContaining if You wish to launch SQL query like: ... WHERE firstname LIKE "%name%"
Using Spring, I suggest not using JpaRepository if You don't need to. The simplest implementation is CrudRepository and it covers most use cases.
In summary, Your method should be simplified and look somewhere like that:
public interface UserRepository extends CrudRepository<User, Long> {
User findOneByLastnameContainingOrFirstnameContaining(String lastname, String firstname);
}
This should result in query:
SELECT * FROM User u WHERE u.lastname LIKE '%lastname' OR u.firstname LIKE '%firstname%;'

Categories