Print Records from FindAll() in CrudRepository - java

I am extending CrudRepository in my Repository class. I want to print the records in my table using the findAll method. So far, I have written a test class, and I can see the result query is correct. How can I print the individual records in the table?
Here is a snippet of my code:
Repository Class
public interface RepositoryAda extends CrudRepository{
}
Service Class
#Service
public class Service{
#Autowired private RepositoryAda repository;
#Transactional
public List selectRecords(){
return (List) repository.findAll();
}
}
Test Case:
#Test
public void getAllRecords() {
service.selectRecords();
}
How can I print the individual records from the table to a console?

I prefer to use Google's Guava when using the repository interfaces. You can turn findAll() Iterable into a List<Type> with one line.
public RecordRepository extends CrudRepository<Record, Long> {}
public class RecordServiceImple implements RecordService {
RecordRepository recordRepository;
public List<Record> selectRecord() {
return Lists.newArrayList(recordRepository.findAll()); // Guava library
// or just simply cast it.
// return (List<Record>)recordRepository.findAll();
}
}
Then just loop through the list
for (Record record : records) {
System.out.println(record);
}
Just overrive the toString() in your Record class, or whatever your class name is, to tabular formatting using String.format()

Related

how to look if List exists in DB in Springboot

I have a springboot application where I am saving a list with my Meeting Entity. I can save my entities all at once, but I want to check before each save if one entity inside my list already exists inside my Db and then just save the ones which are not inside. But I am kinda stuck and do not know how to do it. Could someone look at my code and give me an advice?
MeetingController:
#PostMapping("/")
public void saveMeeting(#RequestBody List<Meeting> meeting){
List<Meeting> exist =
meetingService.findAllMeetingsWithName(meeting.stream().map(m -> m.getMeetingName()).collect(Collectors.toList()));
meeting.removeAll(exist);
meetingService.saveMeeting(meeting);
}
MeetingService:
public void saveMeeting(List<Meeting> meeting){
meetingRepository.saveAll(meeting);
}
Repository:
#Repository
public interface MeetingRepository extends JpaRepository<Meeting, Long> {
}
This is the functionality that you want
#Transactional
public void saveMeeting(List<Meeting> meeting){
List<Meeting> alreadyExist = meetingRepository.findByMeetingNameIn(meeting.stream().map(m -> m.getMeetingName()).collect(Collectors.toList());
meeting.removeAll(alreadyExist);
meetingRepository.saveAll(meeting);
}
and then just define that repository method
#Repository
public interface MeetingRepository extends JpaRepository<Meeting, Long> {
List<Meeting> findByMeetingNameIn (List<String> meetingNames);
}
Remember to override equals and hashcode in Meeting entity to consider the id field.
You can check whether your meetings are in the DB. Try this.
List<Meeting> findByValueIn(List<Meeting> values);
Since you already are planning to use JpaRepository, take advantage of the #Query and batch queries
#Repository
//custom query using IN
public interface MeetingRepository extends JpaRepository<Meeting, Long>
{
#Query("SELECT m from MEETING m where m.name IN (:names)")
public List<Meetings> findAllMeetingWithNames(List<String> meetings)
}
#Service
class MeetingService{
private MeetingRepository meetingRepository;
...
//other code....
#Autowired
public MeetingService(MeetingRepository meetingRepository){
this.meetingRepository = meetingRepository;
}
public void saveAllMeetings(List<Meeting> meetings){
//call repository custom query here
names = meetings.stream()
.map((m) -> m.name)
.collect(Collectors.toList());
List<Meeting> existingMeetings = meetingRepository.findAllMeetingWithNames(names);
//delete using a single query
meetingRepository.deleteAllInBatch(existingMeetings);
meetingRepository.saveAllAndFlush(meetings);
}
.....
}

how to design storage for transactions involving multiple tables in dynamodb?

I am trying to add transaction support to an existing dynamodb storage which looks like this:
public interface Storage<T>{
T put(T entity);
...
}
public abstract class AbstractDynamoStorage<T> implements Storage<T> {
#Override
public T put(T entity) {
...
}
}
public class DynamoOrderStorage extends AbstractDynamoStorage<CoreOrder> {
...
}
public class DynamoCustomerStorage extends AbstractDynamoStorage<CoreCustomer> {
...
}
Now, I want to add transaction support to this using the newly launched DDB transactions to be able to commit multiple operations(put, write, update..) across multiple tables.
Here's my approach:
interface TransactDAO{
void commitWriteTransaction(TransactWriteRequest writeReq);
}
class DynamoTransactImpl implements TransactDAO{
#Override:
commitWriteTransaction(TransactWriteRequest request){
//dynamodb.transactWriteItems();
}
}
class DynamoDBTransactWriteItem implements TransactWriteRequest{
List<DynamoTransactWriteItem<T>> transactWriteItems;
}
class DynamoTransactWritePutItem<T> implements DynamoTransactionWriteItem<T>{
String tableName;
String data;
...
}
My worry is that the concrete storage classes(DynamoOrderStorage and DynamoCustomerStorage) are of different type and my approach might not work here. Is there any other better way to achieve this?

How to use JPQL without #Query annotation inside the method?

I want to use dependency inversion principle inside my book rental project. Before, I used AccountRepository that extends CrudRepository, so my method looked like this:
#Query("SELECT CASE WHEN COUNT(account) > 0 THEN true ELSE false END FROM
Account account WHERE account.id =:accountID")
boolean doesAccountExistsWithGivenID(#Param("accountID") int accountID);
I've created AccountRepository and class that implements this repository.
Class that implements interface is called PostgreSQLAccountRepository. And inside doesAccountExistsWithGivenID I want to query somehow to get same result.
It looks like this:
package bookrental.account;
import bookrental.bookrentals.BookRentals;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public class PostgreSQLAccountRepository implements AccountRepository {
private CrudRepository<Account, Integer> repository;
public PostgreSQLAccountRepository(CrudRepository<Account, Integer> repository) {
this.repository = repository;
}
#Override
public List<BookRentals> getAccountRentalsByGivenID(int accountID) {
//TODO
}
#Override
public void deleteById(Integer id) {
this.repository.deleteById(id);
}
#Override
public List<Account> findAll() {
return (List<Account>) this.repository.findAll();
}
#Override
public boolean doesAccountExistsWithGivenID(int accountID) {
//HERE I WANT TO USE JPQL
}
``}
I do not want to use existsByID, because I have a lot of methods that use JPQL so I need to know how to implement it inside the method.
The documentation is clear on how to customize methods from a Data repository:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
Basically define the fragment of the interface you want to customize (CustomizedRepository). Extend this interface in your data repository
interface SomeRepositry extends CrudRepository<...>, CustomizedRepository
Create implementation for CustomizedRepository called CustomiyedRepositoryImpl. The Impl postfix is critical here. See the docs for more customizations.
You will need to autowire the SessionFactory and use it manually.
#Autowired
public setSessionFactory(EntityManagerFactory factory) {
if(factory.unwrap(SessionFactory.class) == null){
throw new NullPointerException("factory is not a hibernate factory");
}
this.hibernateFactory = factory.unwrap(SessionFactory.class);
}
After you have access to it, then you can use it directly
Session session = hibernateFactory.createSession();
Query query = session.createQuery("SELECT CASE WHEN COUNT(account) > 0 THEN true ELSE false END FROM Account account WHERE account.id =:accountID");
query.setParameter("accountId", "7277");
List list = query.list();

What's the correct way to find all entities ordered by field in Spring Data?

I'm using Spring Data JPA and want to add a method in my base Repository interface to get all entities ordered by field order:
#NoRepositoryBean
public interface OrderedEntityDao<T extends OrderedEntity> extends EntityDao<T, Long> {
List<T> findOrderByOrder();
}
OrderedEntity is a #MappedSuperclass entity.
But I'm getting exception when creating this bean:
Caused by: java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:854)
at org.springframework.data.jpa.repository.query.ParameterMetadataProvider.next(ParameterMetadataProvider.java:121)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:274)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:180)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:109)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:49)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:118)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$CountQueryPreparer.<init>(PartTreeJpaQuery.java:241)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:68)
How to write this method correct?
Edit:
#MappedSuperclass
public abstract class OrderedEntity extends IdEntity implements Comparable<OrderedEntity> {
#Nonnull
#Column(name = "`order`")
private Long order;
}
The correct named query will be:
public interface OrderedEntityDao<T extends OrderedEntity> extends EntityDao<T> {
public List<T> findAllByOrderBy<colname><Desc|Asc>();
}
In your case:
public List<T> findAllByOrderByOrderDesc();
public List<T> findAllByOrderByOrderAsc();
I think this below code is work,
#NoRepositoryBean
public interface OrderedEntityDao<T extends OrderedEntity> extends EntityDao<T, Long> {
List<T> findAllOrderByOrderAsc();
}
It should be
public List<T> findByOrder(Long order);
The correct syntax for query methods with Spring Data is basically findBy followed by the variable names, separated with And/Or. Refer to the full documentation here.

How to extract "find or create" method to abstract class? (Spring Data Jpa)

I'm using Spring Data JPA and I have a bunch of repositories like this one:
public interface CustomerRepository extends JpaRepository<Customer, Long> {}
Under repositories I have services and a lot of them need to have implemented method findOrCreate(String name) like this one:
#Override
#Transactional
public List<Customer> findOrCreate(final String name) {
checkNotNull(name);
List<Customer> result = this.customerRepository.findByName(name);
if (result.isEmpty()) {
LOGGER.info("Cannot find customer. Creating a new customer. [name={}]", name);
Customer customer = new Customer(name);
return Arrays.asList(this.customerRepository.save(customer));
}
return result;
}
I would like to extract method to the abstract class or somewhere to avoid implementing it for each services, testing and so on.
Abstract class can be look like this:
public abstract class AbstractManagementService<T, R extends JpaRepository<T, Serializable>> {
protected List<T> findOrCreate(T entity, R repository) {
checkNotNull(entity);
checkNotNull(repository);
return null;
}
}
And the problem is it due to the fact that I need to find object by name as a string before creating a new one. Of course interface JpaRepository doesn't offer this method.
How can I solve this problem?
Best Regards
Create a custom JpaRepository implementation that includes this behaviour. See this post for an example of writing a custom JpaRepository implementation.

Categories