I got database with several collections in micorservice, so there's controllers which works fine. But I need to collect statistics from servers, including database. There's a good query serverStats() which gives all the information about the server, but how can I pass it through app layers?
I made interface repository extended ReactiveCrudRepository using SomeModel class as a place holder and wrote one method like String getStatistics() with #Query annotation, but it doesn't work
public interface MongoMonitoring extends ReactiveCrudRepository<SomeModel, String> {
#Query("{ serverStatus: 1 }")
String getStatus();
Use MongoTemplate. The code like:
private MongoTemplate mongoTemplate;
Document result = this.mongoTemplate.executeCommand("{ serverStatus: 1 }");
The document is from package org.bson.Document which is like JSON.
Related
I have a spring boot app with a MongoDB connection. On using the POJO/Model class with #Document(Collection = "CompanyDetails"), it successfully creates the collection in MongoDB after "POSTMAPPING" and the result goes inside the CompanyDetails collection as expected.
I have used controller, service, repository, and used the Map<String, Object> in parenthesis of the repository rather than using POJO class.
Controller:
#PostMapping("/addRecords")
public Map<String, Object> addCompanyDetails(#RequestBody Map<String, Object> companyDetails) {
return companyDetailsService.addCompanyDetails(companyDetails);
}
Service:
#Service
public class CompanyDetailsService {
#Autowired
CompanyDetailsRepository companyDetailsRepository;
public Map<String, Object> addCompanyDetails(Map<String, Object> companyDetails) {
return companyDetailsRepository.insert(companyDetails);
}
}
Repository:
#Repository
public interface CompanyDetailsRepository extends MongoRepository<Map<String, Object>, String> {}
My requirement is to create a collection without a POJO class. Because, the fields are not fixed(while inserting records). So, I can't declare fields in the POJO class & generate a getter setter.
As I'm not using the POJO class, when I POST record, it creates a collection with the name "map" & insert records inside that.
But, expected was to create "CompanyDetails" collection & store data inside that.
Yes, people using MongoDB faced this issue as MongoDB is a schemaless database and creating POJO will be difficult. So, here is the solution for such use-cases.
Firstly, you can use the MongoClient to connect with your database. Check out this document for your reference: Connect to MongoDB
Secondly, you can create databases and collections using that `mongoClient object. Check out this document for your reference Create database and collection
Finally, you can use some generic objects like HashMap or BasicDBObject to perform your CRUD operation
My project involves using GraphQL within a Spring Boot app. For demonstration purposes, here is my GraphQL schema:
type Company{
name: String,
parentOrganization: String,
flag:Int
}
I'm still learning Spring Boot and JPA, so I use spring-boot-starter-data-jpa for all the JPA, Hibernate, etc.
My problem is, when someone queries only for name and organization, Hibernate queries for all the columns and GraphQL picks the columns requested.
#Repository
#Transactional
public interface CompanyRepository extends JpaRepository<Company,Long> {
}
The above code doesn't really give me any flexibility in limiting the columns that are queried. I've tried using Hibernate's Criteria API as well, but whichever way I go, I get this error:
Unable to locate appropriate constructor on class [packagee.entity.company]. Expected arguments are: java.lang.String, java.lang.String [select new package.entity.Company(generatedAlias0.company, generatedAlias0.organization) from package.entity.Company as generatedAlias0]
Below is the code for my Criteria implementation:
public static List<Company> get(EntityManager em, List<String> fieldsAsked){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Company> cq = cb.createQuery(Company.class);
Root<Company> root = cq.from(Company.class);
List<Selection<?>> selectionList = new LinkedList<Selection<?>>();
for(String name: fieldsAsked){
selectionList.add(root.get(name));
}
cq.multiselect(selectionList);
return em.createQuery(cq).getResultList();
}
How do I get limited columns from Hibernate? I've seen many answers online that ask to make appropriate constructor in the entity class, but that's not really possible for me because my entity parameters are mostly Strings and I cant make constructors for all the permutations possible (because I'm using GraphQL, the control of what to query really goes to the end user of my project).
What should I do? Thanks in advance!
What you want to do is not really possible with Hibernate directly, but you can checkout Blaze-Persistence Entity-Views which also has a GraphQL integration that supports exactly what you are looking for. See https://persistence.blazebit.com/documentation/1.6/entity-view/manual/en_US/#graphql-integration
Here is a sample project that shows how you can use this: https://github.com/Blazebit/blaze-persistence/tree/master/examples/spring-data-graphql
Solution 1:
You can create a new DTO class which will be returned by your query.
The DTO class:
public class CompanyDTO(){
//fields,constructor
}
And in the repository:
#Query(value = "SELECT new com.example.dto.companyDTO" +
"(c.name,c.parentOrganization)" +
" FROM Company c")
List<CompanyDTO>findCompanySelectedColumns(PageRequest pageable);
Solution 2(clean solution):
You can use interface. Do not implement the interface.
interface customCustomer{
String getName();
String getParentOrganization();
}
In repository:
List<CustomCustomer>findAllByNameAndParentOrganization();
I have four tables in a database. When the user uses the Search option from the React application I want the search button to query all the tables and display data from all the tables which is AWS RDS MYSQL. How should I proceed? I am using Spring boot, mysql, and react.
I would recommend taking a look at JPA Respositories. Since your db seams to be small, a simple repository method like that one should make the trick.
However, if you have a more complicated requirement, you can use a Spring Projection. Create a query that retrieves all the fields you'll need, even if they're from different tables, and map the result into a Spring Projection
Using spring data jpa you should create a method in your repository that returns a list of your projection class:
public interface MyRepository extends Repository<MyEntityProjection, Long> {
#Query("SELECT ... WHERE field = ?1")
List<MyEntityProjection> getData(String param);
}
The projection class should be something like this:
public interface MyEntityProjection {
String getField();
String getField2();
}
Adding as many fields as your query returns.
Read the docs I linked for more information and examples.
I am using a Spring web service and MongoDb to hold my data. Currently my Repository class extends MongoRepository and an obj of its interface gets injected into my Controller.
There is no method for finding and deleting a specific entity in the MongoRepository interface. How can I do this without having to provide a concrete implementation? I need to do the operation at the same time.
Here's my code on github if its useful: https://github.com/RyanNewsom/DentistAppointmentSchedulerService
I ended up figuring this one out. I made a custom class and used MongoTemplate. You can then submit a query using mongoTemplate. It contains a lot more mongo specific implementation.
#Repository
public class AppointmentCustomRepository {
#Autowired
MongoTemplate mongoTemplate;
public Appointment getAppointmentAndDelete(String id) {
return mongoTemplate.findAndRemove(Query.query(Criteria.where("id").is(id)), Appointment.class);
}
}
Sample snippet to find and delete one document in Mongo DB using Java API's
MongoCollection<Document> collection = database.getCollection("PasstheCollectionName");
Document document = collection.find.first();
Object value = document.get("_id");
Bson filter = Filter.and(Filter.eq("_id",value));
collection.findOneAndDelete(filter);
#Repository
public interface UserDao extends User {
public List<User> findByFirstname(String firstname);
}
How could I use above code to retrieve all records?
I tried findByFistname(null);, it doesn't work...
I don't want to use findByFirstname(); because it's possible to have parameter.
Hope you all understand.
Have you considered using a spring data specification? In spring data a specification is a way to wrap the JPA criteria api.
The idea behind the JPA Criteria api is to generate queries programatically, by defining query objects.
Once you have encapsulated the criteria in a specification objects, a single findAll method can be used in a number of scenarios. For example programatically add criteria based input form the user, such as additional search filters etc.
To use this feature a repo will need to extend "JpaSpecificationExecutor"
public interface UserRepository extends JpaRepository<User>, JpaSpecificationExecutor {
List<T> findAll(Specification<T> spec);
}
The find method can then be called with multiple criteria, or the criteria can be built dynamically based on the situation:
List<User> users = userRepository.findAll(where(userLastNameIs("John")).and(userIsArchived()));
Alternatively you can also try query by exampe. The idea here is to provide the actual domain object with the populated search fields to an example matcher. Configure the example matcher to control the search and pass it to the findAll method.
Again the repo will need to implement an interface. Check the documentation for the detailed pros/cons of each approach.
Person person = new Person();
person.setFirstname("Dave");
ExampleMatcher matcher = ExampleMatcher.matching()
.withIgnorePaths("lastname")
.withIncludeNullValues()
.withStringMatcherEnding();
Example<Person> example = Example.of(person, matcher);
List<Person> people = personRepository.findAll(example);
You should extend your repository from JpaRepository. Be careful with name of repository (It should follow convention). After you inject your UserRepository bean you will have already implemeted by spring data crud methods like findOne(), findAll(), delete() etc.
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
//assume your primary key is Long type
}
Also will be useful documentation
As I got from comments you're trying to achieve ignorance of null values of passed parameters (instead of retrieving all records by findAll()).
Unfortunately, currently, it's not supported by Spring .
You could leverage the #Query annotation and write the query manually in such manner:
#Query("select u from User u where "
+ "(:firstname is null or u.firstname = :firstname)"
+ "(:lastname is null or u.lastname = :lastname)"
)
public List<User> findUserByFirstNameAndLastName(
#Param("firstname") String firstname,
#Param("lastname") String lastname
);
https://spring.io/blog/2011/02/10/getting-started-with-spring-data-jpa/
This is very good tutorial of Spring Data. I suggest you to start with it. tutorial of Spring Data. If you want to go deeper you can read the documentation.
http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html