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
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);
}
.....
}
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?
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();
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.
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.