For this question,I am not looking for a solution, but looking for a direction from where I can take myself ahead, hence not sharing any code.
I am preparing a REST API and I have postgresql database setup locally, which has 2 tables and one view from those 2 tables.
Normally when I want to get any data from DB, I use following code(for the sake of clarity):
DataRepository class:
public interface DataRepository extends CrudRepository<Data, String>{}
DataService class:
#Service
public class DataService {
#Autowired
private DataRepository repo;
public Data getData(String id){
return repo.findById(id).orElse(null);
}
}
DataController class:
#RestController
public class DataController{
#Autowired
private DataService service;
#RequestMapping("/{id}")
public Data getData(String id){
return service.getData(id);
}
}
Data class:
#Entity
public class Data{
#Id
private String id;
private String name;
//respective getter and setter methods
}
Now I want to retrieve data from a view, so, what should be the approach for that?
Should we use the same approach of creating Model, Service, Ctonroller and Repository classes?
Can we use CrudRepository to achieve the same?
I searched in a lot of places, but didn't find anything useful.
Let me know if anyone has any clue on this.
The reading methods of a CrudRepository should work fine with a view. For the writing methods, the view needs to be updatableenter link description here.
If you only want to read, but not to write to the repository, you can create a ReadOnlyRepository by copying the source code of the CrudRepository and removing all the writing methods.
Note that JPA will still try to persist changes made to managed entities.
To avoid that and also avoid the cost of dirty checking you can mark your entities as immutable if you are using Hibernate.
Related
I am new in spring and hibernate and I got these two annotations #Entity and #Repository used for DAO class. As both the annotations are used for the DAO class. Then, what is the difference and when to use one of them.
The #Entity class is the model and the #Repository is the layer that helps you to extract the data from database. For example :
#Entity
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(unique=true)
private String name;
//getters - setters
}
And the repository:
#Repository
public interface StudentRepository extends CrudRepository<Student,Long> {
public Student findByName(String name);
}
The basic CRUD operations are already provided by CrudRepository interface so there is no need to implement them again. You can use them in a Service class like this:
#Service
public class StudentServiceImpl implements StudentService {
#Autowired
public StudentRepository studentRepository;
#Override
public List<Student> findAll()
{
return studentRepository.findAll():
}
#Override
public Student findByName(String name)
{
return studentRepository.findByName(name);
}
}
And in case you want to make custom queries like get a student by name, jpa hibernate is very smart and helps you to only define the method in the #Repository annotated interface and there is no need of any implementations. BUT there is a rule here if you want to make it work. Hibernate will look after method name like this : public Student findByName(String name); the find and Student return type tells hibernate that it have to look for a Student, byName will tell that it have to query the database for a Student with a specific name. (The Name keyword is actually the entity attribute with capital letter ! )
But of course, if you need some more complex queries, there is the #Query annotation that will help you with that :) .
#Entity annotation defines that a class can be mapped to a table, it is just a marker, like for example Serializable interface.
Entity is an object representing (usually) a row in a db.
#Repository annotation defines CRUD operation on table.
It is very like DAO pattern to fetch and save entities from/to storage - it represents db table.
#Entity
Let's say we have a POJO called Student which represents the data of a student and we would like to store it in the database.
public class Student {
// fields, getters and setters
}
In order to do this, we should define an entity so that JPA is aware of it.
So let's define it by making use of the #Entity annotation. We must specify this annotation at the class level.
#Entity
public class Student {
// fields, getters and setters
}
In most typical applications, we have distinct layers like data access, presentation, service, business, etc.
And, in each layer, we have various beans. Simply put, to detect them automatically, Spring uses classpath scanning annotations.
#Repository
#Repository annotates classes at the persistence layer, which will act as a database repository. #Repository’s job is to catch persistence specific exceptions and rethrow them as one of Spring’s unified unchecked exception.
to sum up #Entity is part of JPA Java Persistence API specification used mapping between a java POJO and an entity in relational database world and #Repository is a Spring stereotype used to annotate POJO beans than their jobs is database manipulation operations
I naively implemented a web service, that consumes a list of Json objects and stores them in a SQL database using
springframework.data.jpa (JPA & Hibernate). However, the solution has a low performance and the profiler gave me a hint that the main problem lies in creating the entities from the Json objects one by one.
The code below is simplified, but basically: for each Json object in the incoming list there are two entities created: DataEntity and IdentityEntity. The former holds the data of interest and uses the latter as FK, which has a compound PK of a time and a person.
I'd like to speed up the storage process. I've determined with a profiler, that there are too many flush operations that are being done after insert of each new entity. Since I need to insert thousands of records at a given time, this causes the performance issue. Can I perhaps do the insert in one transaction or what are other ways of optimizing it?
Data class (I have many similar classes):
#Entity
public class DataEntity {
#EmbeddedId
private IdentityEntity identity;
private Double data;
}
Embeddable entity:
#Embeddable
public class IdentityEntity implements Serializable {
#NonNull
private Long personId;
#NonNull
private Long datetimeId;
}
JPA repository:
#Repository
public interface DataRepository extends JpaRepository<DataEntity, IdentityEntity> {}
Simplified controller:
public class DataController{
#Autowired
private DataRepository dataRepository;
#Autowired
private DatetimeRepository datetimeRepository;
#PostMapping("/upload")
public void upload(...List<DataJson> items) {
PersonEntity person = getPerson(...); // fast enough
for (DataJson i : items) { // begin transaction here?
saveNewEntity(i, person.getId());
}
}
private void saveNewEntity(DataJson json, Long personId) {
TimeEntity savedDatetime = datetimeRepository.save(new TimeEntity(json.getDatetime()));
IdentityEntity mi = IdentityEntity(personId, savedDatetime.getId());
DataEntity entry = new DataEntity(mi, json.getData());
dataRepository.save(entry);
}
}
Edit: After further digging into the profiler, I've discovered that another time-consuming operation might be the transaction management itself. Although I haven't implemented or configured any transaction behavior, I suspect that the Spring Boot has something default configured for the Hibernate ORM. I'm beginning to think that a transaction is now being created in every iteration of the loop, being the 1st performance issue and also causing the 2nd issue, where at the end of the transaction everything is flushed and written into the DB.
Yep. All the methods in the SimpleJpaRepository are annotated with #Transactional.
Simply add a #Transactional annotation to your upload method.
... or
First create all of the objects and save them in one go using the save(Iterable<S> entities) method.
So I'm writing a personal project to learn about web programing and I came across the DAO pattern. I'd built some classes (models) and like almost any program, they are nested (ex: the class Payment has a reference to an Author instance).
Just for the reference, I'm not using any mappers (will add them on a later iteration, and I'm using JDBC, not JPA).
My question is this:
When I create the PaymentJdbcDao I had a method what will return some Payment, but in order to create this payment from the database stored object I must reach also the Author (stored in a separated table).
Should I call UserJdbcDao from the PaymentJdbcDao in order to get the payment's author, should I alter the query with a join to retrieve the fields from both entities, should the PaymentJdbcDao call the UserService (I think this isn't good since the services are on the layer abobe the daos), or should I remove the author reference as an object and just hold a reference to the author_id?
Which of the abobe is the more appropriate way to accomplish this? Or is any other way which is a better practice?
Thanks.
I call my DAOs (DataAccessObjects) "Repositories".
Spring Data JPA is doing this as well.
So I would create a UserRepository and a PaymentRepository.
Repositories can be called by other Repositories or Services.
Services should never be called by Repositories.
UI -> Service -> Repository.
Your PaymentRepository could return an Entity like this
public class PaymentEntity{
private long id;
private DateTime dateTime;
private UserEntity user;
}
Your UserRepository could return an Entity like this
public class UserEntity{
private long id;
private DateTime lastLogin;
private List<PaymentEntity> payments;
}
Your Repositories could look like this.
public interface PaymentRepository{
PaymentEntity getPaymentById(long id);
List<PaymentEntity> getAllPayments();
}
public interface UserRepository{
UserEntity getUserById(long id);
List<UserEntity> getAllUsers();
}
So your PaymentRepository would call the UserRepository to get the User for your Payment.
And your UserRepository would call the PaymentRepository to get all users Payments
I hope I was able to help you
I am using spring data jpa for my project and i have following pieces of code:
My Repository:
#Repository
#Transactional
public interface StudentRepository extends PagingAndSortingRepository<Student, Long> {
List<Student> findByIdIn(List<Long> ids);
}
and my entity is :
#Entity
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
// other fields
// getters/setters
}
Somewhere in my service class, i have
#Autowired
StudentRepository studentRepository;
and then i call findByIdIn from my service layer like :
studentRepository.findByIdIn(listOfIds);
findByIdIn(listOfIds) method works perfectly fine and everything is working as expected.
I know that the implementation of findByIdIn() method is provided by spring data jpa.
But i am not able to figure where is its implementation present?
What exactly is its implementation?
Are such methods generated at run time depending upon the method-name? If yes how are they generated and executed dynamically?
Thanks!
You can dig a little bit in the core of the Spring code to see how it works (https://github.com/spring-projects/spring-data-commons/tree/master/src/main/java/org/springframework/data/repository), but basically, it's parsing the interface methods into HQL at the startup time.
You can test just be editing a method name to a field which doesn't exist, and you'll get an error at startup time saying that there is no field as this.
It's about passing interface of DTO to DAO.
For example I have following code
public interface User {
String getName();
}
public class SimpleUser implements User {
protected String name;
public SimpleUser(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
// Mapped by Hibernate
public class PersistentUser extends SimpleUser {
private Long id;
// Constructor
// Getters for id and name
// Setters for id and name
}
I'm using generic DAO. Is it ok if I create DAO with using interface User instead PersistentUser?
User user = new PersistentUser(name);
UserDao.create(user);
I read a lot of topics on stack but not figured out is this approach ok or no. Please help me. Maybe this is stupid and I can achive only problems.
About separating beans.
I did this because some classes I want to share via API module, that can be used outside to create entities and pass them to my application. Because they uses interface I developed so I can pass them to my DAO for persisting.
Generally, I would say it is ok, but there are a few hidden problems. A developer could cast the object down or access some state via a toString method that shouldn't be accessible. If you don't be careful, it could happen that state is serialized as JSON/XML in webservices that shouldn't be serialized. The list goes on.
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(PersistentUser.class)
interface User {
String getName();
}
Querying could look like this
List<User> dtos = entityViewManager.applySetting(
EntityViewSetting.create(User.class),
criteriaBuilderFactory.create(em, PersistentUser.class)
).getResultList();