I have defined some beans to be stored in a Mongo Database. I am using Quarkus Panache MongoDB.
It works if I annotate the domain classes with #MongoEntity
#MongoEntity(collection="ThePerson")
public class Person {
public ObjectId id;
public String name;
...
}
I want to avoid the #MongoEntity in these classes, to put these clases in a separated package and not depend on the Panache, or even any quarkus dependency.
How can I configure these external beans?
Why? I want to share a package to help other teams that don't use quarkus but will use the same model.
What if you share an interface with all the getters for example? So you can easily share your interfaces in packages/libs.
With this approach, suppose you are going to expose your models over some REST apis returning Jsons for your clients, you can create a utility jar/package that automatically converts the Json for your pojos.
//your abstration
interface BasePerson {
ObjectId id();
String name();
...
}
//your model/entity
#MongoEntity(collection="ThePerson")
public class Person implements BasePerson {
public ObjectId id;
public String name;
...
}
Related
I have a spring-data-jpa application and a library. The library contains a class, lets say Car.java
public class Car{
Long id;
String name;
String color;
.. getter and setter
}
In my application I need to store this object and want to use rest repositories. For that I need to annotate the class:
#Entity
#Table(name = "customerCar")
public class CarEntity{
#Id
Long id;
String name;
String color;
.. getter and setter
}
Is there a way to do this without code duplication and/or without make a copy?
CarEntity customerCar = new CarEntity();
customerCar.setId(car.getId());
....
Use mapper framework to avoid copying boilerplate code.
You can choose to use the JMapper mapping library based on the performance benchmarking mentioned below:
https://www.baeldung.com/java-performance-mapping-frameworks
At least I endet in a very similar approach to #sham. I used the copy properties function of the BeanUtils Class from Spring Framework
org.springframework.beans.BeanUtils;
BeanUtils.copyProperties(car,carEntity);
Is there any approach to convert entity to dto object partially? Or are there any best practices for using the entity, pojo/dto and response object in MVC pattern?
You have couple of approaches. I assume you have a web project.
Manual mapping approach. Create Dto map it manually to your entity. This would involve all the boilerplate code around it - Builders, all argument Constructor, getters, setters whatever approach you will use to populate the DTO.
The different hydration Technics apply in different situations. Builder pattern presumes you would have an immutable objects. Getters and Setters are supported out opf the box by frameworks as Jackson. You may decide to minimize your boilerplate code by using lombok, imutables or other frameworks.
Mapping framework. Another option would be to use a supplied mapper like ObjectMapper, or FastMap there may be other choices. This would remove large portion of manual mapping you would need to establish following aproach 1.
Deserializer. Example of such aproach would be spring-data-rest where your repository returns the entities straight which are than serialized in JSON . Using normal spring MVC this would be to return your entity straight to your controller layer and based on annotations or other means (serializers) map it to your network format JSON, XML whatever you use.
These are the different options. Which one is best depends on your usecase.
One of possible approaches is copy constructor. The example below.
// entity annotations ...
public class EntityExample {
private Long id;
private String name;
private Integer score;
// getters and setters ...
}
public class DtoExample {
private Long id;
pricate String name;
// For serialization and deserialization
public DtoExample() {
}
public DtoExample(EntityExample entity) {
this.id = entity.getId();
this.name = entity.getName();
}
// getters and setters ...
}
I'm using MongoDB in my spring boot based application. I persist a set of entities which look like this:
#Document(collection = "users")
public class User {
#Id
private String id;
private String email;
}
It has some required annotations in order to be persisted by spring data.
Now I want to extract all entity classes from my maven module and include them in a new api-module which we'll be shared among other different modules in my project.
I don't want to include mondodb-related annotations into this module, I want it to be simple java classes like this.
public class User {
private String id;
private String email;
}
So when I will use it in my module (with mondogdb) I will have to add the appropriate annotations:
#Document(collection = "users")
public class UserEntity extends User {
}
So the only one way I can see is to extend POJO and enhance it with mongo annotations.
The question is are there any better ways how this can be implemented. Couldn't find any solutions yet.
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();
How can I create collection OneToMany without using annotations?
Now I'm using DatabaseFieldConfig like this:
DatabaseFieldConfig collection = new DatabaseFieldConfig("name");
collection.setForeignCollection(true);
But it doesn't work because I always get "Not fields has DatabaseField annotation" when I'm trying to create Dao.
Below is my example code:
public class HasCollection {
private long id;
private Collection<CollElement> coll;
...
}
public class CollElement {
private long id;
private HasCollection parent;
...
}
When I'm creating DAO for HasCollection I get error that "Not fields has DatabaseField annotation in CollElement" and if I'm creating DAO for CollElement I get error "Not fields has DatabaseField annotation in HasCollection"
I made a sample code when extending class but it would drag dependency on ormlite DAO into this extended model class which is definitly not the right pattern.
Therefore in this case I would consider the class from another project as a DTO (data transfer object) and I would create another model class with annotations for ormlite.
Than made a simple convertor from DTO to the model class and vice versa used in layer where you want to persist objects.