Is it possible to create a template/live template with IntelliJ to create the full stack of usual boilerplate for a Domain Object?
Let me give you an example: A usual structure in in a backend could look something like this:
Define a functional domain object: Foobar
Create the entity FoobarEntity:
#Entity #Table(name="foobar") #Getter #Setter
public class FoobarEntity implements Persistable<Long> {
#Id
private Long id;
#Column
private String someData;
#Column
private String someMoreData;
}
Now the boilerplate party starts, create data transfer objects, data access objects, services, ...: Create FoobarDto (to get started), Interface FoobarDao (CRUD) and default implementation FoobarDaoJpa, Interface FoobarService (CRUD) and default implementation FoobarServiceImpl, a mapper to map from Entity to Dto FoobarDtoMapper, maybe a Spring config FoobarConfig, maybe a filter object to search FoobarSearchFilter, maybe some more Classes for a REST api like FoobarRessource, FoobarController, ...
Some further considerations: More annotations (like #Service or something like that) would be somehow useless since the all the classes start with the same code base (like add, delete, edit, load methods for a service and a dao) but, however, will grow in the further process of development.
Is this somehow possible with IntelliJ (or another tool you know)?
You can create entities like that with hibernate plugin. It creates entities according to your table structure. Just add hibernate framework to your project (in linux, press Ctrl + Shift + a, then type hibernate and select add hibernate framework), then you'll get a task window like that:
Now right click on your projects name (will be different in your case) and select Generate Persistence Mapping > By Database Schema.
Now a window will open and you can select the tables you want to create an entity for.
Note that you need to have set up your database in idea to make this work.
For your third point, use file templates. Again, press Ctrl + Shift + a, but then type file template - create the templates once and just use them...
Related
So I'm trying for the first time in a not so complex project to implement Domain Driven Design by separating all my code into application, domain, infrastructure and interfaces packages.
I also went with the whole separation of the JPA Entities to Domain models that will hold my business logic as rich models and used the Builder pattern to instantiate. This approach created me a headache and can't figure out if Im doing it all wrong when using JPA + ORM and Spring Data with DDD.
Process explanation
The application is a Rest API consumer (without any user interaction) that process daily through Scheduler tasks a fairly big amount of data resources and stores or updates into MySQL. Im using RestTemplate to fetch and convert the JSON responses into Domain objects and from there Im applying any business logic within the Domain itself e.g. validation, events, etc
From what I have read the aggregate root object should have an identity in their whole lifecycle and should be unique. I have used the id of the rest API object because is already something that I use to identify and track in my business domain. I have also created a property for the Technical id so when I convert Entities to Domain objects it can hold a reference for the update process.
When I need to persist the Domain to the data source (MySQL) for the first time Im converting them into Entity objects and I persist them using the save() method. So far so good.
Now when I need to update those records in the data source I first fetch them as a List of Employees from data source, convert Entity objects to Domain objects and then I fetch the list of Employees from the rest API as Domain models. Up until now I have two lists of the same Domain object types as List<Employee>. I'm iterating them using Streams and checking if an objects are not equal() between them if yes a collection of List items is created as a third list with Employee objects that need to be updated. Here I've already passed the technical Id to the domain objects in the third list of Employees so Hibernate can identify and use to update the records that are already exists.
Up to here are all fairly simple stuff until I use the saveAll() method to update the records.
Questions
I alway see Hibernate using INSERT instead of updating the list of
records. So If Im correct Hibernate session is not recognising the
objects that Im throwing into it because I have detached them when I
used the convert to domain object?
Does anyone have a better idea how can I implement this differently or fix
this problem?
Or should I stop using this approach as two different objects and continue use
them as rich Entity models?
Simple classes to explain it with code
EmployeeDO.java
#Entity
#Table(name = "employees")
public class EmployeeDO implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public EmployeeDO() {}
...omitted getter/setters
}
Employee.java
public class Employee {
private Long persistId;
private Long employeeId;
private String name;
private Employee() {}
...omitted getters and Builder
}
EmployeeConverter.java
public class EmployeeConverter {
public static EmployeeDO serialize(Employee employee) {
EmployeeDO target = new EmployeeDO();
if (employee.getPersistId() != null) {
target.setId(employee.getPersistId());
}
target.setName(employee.getName());
return target;
}
public static Employee deserialize(EmployeeDO employee) {
return new Country.Builder(employee.getEmployeeId)
.withPersistId(employee.getId()) //<-- Technical ID setter
.withName(employee.getName())
.build();
}
}
EmployeeRepository.java
#Component
public class EmployeeReporistoryImpl implements EmployeeRepository {
#Autowired
EmployeeJpaRepository db;
#Override
public List<Employee> findAll() {
return db.findAll().stream()
.map(employee -> EmployeeConverter.deserialize(employee))
.collect(Collectors.toList());
}
#Override
public void saveAll(List<Employee> employees) {
db.saveAll(employees.stream()
.map(employee -> EmployeeConverter.serialize(employee))
.collect(Collectors.toList()));
}
}
EmployeeJpaRepository.java
#Repository
public interface EmployeeJpaRepository extends JpaRepository<EmployeeDO, Long> {
}
I use the same approach on my project: two different models for the domain and the persistence.
First, I would suggest you to don't use the converter approach but use the Memento pattern. Your domain entity exports a memento object and it could be restored from the same object. Yes, the domain has 2 functions that aren't related to the domain (they exist just to supply a non-functional requirement), but, on the other side, you avoid to expose functions, getters and constructors that the domain business logic never use.
For the part about the persistence, I don't use JPA exactly for this reason: you have to write a lot of code to reload, update and persist the entities correctly. I write directly SQL code: I can write and test it fast, and once it works I'm sure that it does what I want. With the Memento object I can have directly what I will use in the insert/update query, and I avoid myself a lot of headaches about the JPA of handling complex tables structures.
Anyway, if you want to use JPA, the only solution is to:
load the persistence entities and transform them into domain entities
update the domain entities according to the changes that you have to do in your domain
save the domain entities, that means:
reload the persistence entities
change, or create if there're new ones, them with the changes that you get from the updated domain entities
save the persistence entities
I've tried a mixed solution, where the domain entities are extended by the persistence ones (a bit complex to do). A lot of care should be took to avoid that domain model should adapts to the restrictions of JPA that come from the persistence model.
Here there's an interesting reading about the splitting of the two models.
Finally, my suggestion is to think how complex the domain is and use the simplest solution for the problem:
is it big and with a lot of complex behaviours? Is expected that it will grow up in a big one? Use two models, domain and persistence, and manage the persistence directly with SQL It avoids a lot of caos in the read/update/save phase.
is it simple? Then, first, should I use the DDD approach? If really yes, I would let the JPA annotations to split inside the domain. Yes, it's not pure DDD, but we live in the real world and the time to do something simple in the pure way should not be some orders of magnitude bigger that the the time I need to to it with some compromises. And, on the other side, I can write all this stuff in an XML in the infrastructure layer, avoiding to clutter the domain with it. As it's done in the spring DDD sample here.
When you want to update an existing object, you first have to load it through entityManager.find() and apply the changes on that object or use entityManager.merge since you are working with detached entities.
Anyway, modelling rich domain models based on JPA is the perfect use case for Blaze-Persistence Entity Views.
Blaze-Persistence is a query builder on top of JPA which supports many of the advanced DBMS features on top of the JPA model. I created Entity Views on top of it to allow easy mapping between JPA models and custom interface defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure the way you like and map attributes(getters) via JPQL expressions to the entity model. Since the attribute name is used as default mapping, you mostly don't need explicit mappings as 80% of the use cases is to have DTOs that are a subset of the entity model.
The interesting point here is that entity views can also be updatable and support automatic translation back to the entity/DB model.
A mapping for your model could look as simple as the following
#EntityView(EmployeeDO.class)
#UpdatableEntityView
interface Employee {
#IdMapping("persistId")
Long getId();
Long getEmployeeId();
String getName();
void setName(String name);
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
Employee dto = entityViewManager.find(entityManager, Employee.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features and it can also be saved back. Here a sample repository
#Repository
interface EmployeeRepository {
Employee findOne(Long id);
void save(Employee e);
}
It will only fetch the mappings that you tell it to fetch and also only update the state that you make updatable through setters.
With the Jackson integration you can deserialize your payload onto a loaded entity view or you can avoid loading alltogether and use the Spring MVC integration to capture just the state that was transferred and flush that. This could look like the following:
#RequestMapping(path = "/employee/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateEmp(#EntityViewId("id") #RequestBody Employee emp) {
employeeRepository.save(emp);
return ResponseEntity.ok(emp.getId().toString());
}
Here you can see an example project: https://github.com/Blazebit/blaze-persistence/tree/master/examples/spring-data-webmvc
I am new to Java and started with Spring Boot and Spring Data JPA, so I know 2 ways on how to fetch data:
by Repository layer, with Literal method naming: FindOneByCity(String city);
by custom repo, with #Query annotation: #Query('select * from table where city like ?');
Both ways are statical designed.
How should I do to get data of a query that I have to build at run time?
What I am trying to achieve is the possibility to create dynamic reports without touching the code. A table would have records of reports with names and SQl queries with default parameters like begin_date, end_date etc, but with a variety of bodies. Example:
"Sales report by payment method" | select * from sales where met_pay = %pay_method% and date is between %begin_date% and %end_date%;
The Criteria API is mainly designed for that.
It provides an alternative way to define JPA queries.
With it you could build dynamic queries according to data provided at runtime.
To use it, you will need to create a custom repository implementation ant not only an interface.
You will indeed need to inject an EntityManager to create needed objects to create and execute the CriteriaQuery.
You will of course have to write boiler plate code to build the query and execute it.
This section explains how to create a custom repository with Spring Boot.
About your edit :
What I am trying to achieve is the possibility to create dynamic
reports without touching the code. A table would have records of
reports with names and SQl queries with default parameters like
begin_date, end_date etc, but with a variety of bodies.
If the queries are written at the hand in a plain text file, Criteria will not be the best choice as JPQL/SQL query and Criteria query are really not written in the same way.
In the Java code, mapping the JPQL/SQL queries defined in a plain text file to a Map<String, String> structure would be more adapted.
But I have some doubts on the feasibility of what you want to do.
Queries may have specific parameters, for some cases, you would not other choice than modifying the code. Specificities in parameters will do query maintainability very hard and error prone. Personally, I would implement the need by allowing the client to select for each field if a condition should be applied.
Then from the implementation side, I would use this user information to build my CriteriaQuery.
And there Criteria will do an excellent job : less code duplication, more adaptability for the query building and in addition more type-checks at compile type.
Spring-data repositories use EntityManager beneath. Repository classes are just another layer for the user not to worry about the details. But if a user wants to get his hands dirty, then of course spring wouldn't mind.
That is when you can use EntityManager directly.
Let us assume you have a Repository Class like AbcRepository
interface AbcRepository extends JpaRepository<Abc, String> {
}
You can create a custom repository like
interface CustomizedAbcRepository {
void someCustomMethod(User user);
}
The implementation class looks like
class CustomizedAbcRepositoryImpl implements CustomizedAbcRepository {
#Autowired
EntityManager entityManager;
public void someCustomMethod(User user) {
// You can build your custom query using Criteria or Criteria Builder
// and then use that in entityManager methods
}
}
Just a word of caution, the naming of the Customized interface and Customized implementating class is very important
In last versions of Spring Data was added ability to use JPA Criteria API. For more information see blog post https://jverhoelen.github.io/spring-data-queries-jpa-criteria-api/ .
I have an issue where I have only one database to use but I have multiple servers where I want them to use a different table name for each server.
Right now my class is configured as:
#Entity
#Table(name="loader_queue")
class LoaderQueue
I want to be able to have dev1 server point to loader_queue_dev1 table, and dev2 server point to loader_queue_dev2 table for instance.
Is there a way i can do this with or without using annotations?
I want to be able to have one single build and then at runtime use something like a system property to change that table name.
For Hibernate 4.x, you can use a custom naming strategy that generates the table name dynamically at runtime. The server name could be provided by a system property and so your strategy could look like this:
public class ServerAwareNamingStrategy extends ImprovedNamingStrategy {
#Override
public String classToTableName(String className) {
String tableName = super.classToTableName(className);
return resolveServer(tableName);
}
private String resolveServer(String tableName) {
StringBuilder tableNameBuilder = new StringBuilder();
tableNameBuilder.append(tableName);
tableNameBuilder.append("_");
tableNameBuilder.append(System.getProperty("SERVER_NAME"));
return tableNameBuilder.toString();
}
}
And supply the naming strategy as a Hibernate configuration property:
<property
name="hibernate.ejb.naming_strategy"
value="my.package.ServerAwareNamingStrategy"
/>
I would not do this. It is very much against the grain of JPA and very likely to cause problems down the road. I'd rather add a layer of views to the tables providing unified names to be used by your application.
But you asked, so have some ideas how it might work:
You might be able to create the mapping for your classes, completely by code. This is likely to be tedious, but gives you full flexibility.
You can implement a NamingStrategy which translates your class name to table names, and depends on the instance it is running on.
You can change your code during the build process to build two (or more) artefacts from one source.
I want to use a simple class with hibernate annotations in a non db project.
I dont wanna dublicate the code and remove annotations.
Is there a way for doing this like using annotations in subclass for parent class's attributes. So i can share the parent class.
Any help would be great, thanks.
Edit:
For example: I have a class:
#Entity
#Table(name = "Sample")
Class Sample{
#Column(name = "attr1")
private String attr1;
// getter setters etc.
}
This class works good for a java project with db dependencies set.
But I serve a restful service with this class.
My client app do not need any db related functions so I dont include any db related jars.
So this is my problem I want to use same classes since both are common for two projects. But I do not need db jars which leads to #Entity annotations to compile errors.
If there is some way to do this, I would be very happy.
Thanks alot.
use hibernate validation groups
Basic Validation Example
create 2 validation groups and use one of them for db project and other for not db project
I am currently working for a client who developed several clean, non-annotated Java POJO domain models. Every domain model contains about 15-50 classes. So far, these Java POJO domain models have only been used in Android apps.
For a new project my client is undertaking, it is necessary to use these domain models server side, and save the instances of their classes to a sql database.
We will use JPA for this. Since the jar needs to be reused in the existing Android apps, using JPA annotations is not an option. So, I need to create JPA xml mappings for these 100+ classes.
I was wondering: is it possible to auto generate JPA Xml mappings from clean Java classes/POJOs using some lib/tool? When I started looking, I thought I was going to find a "javamodel 2 jpa xml mapping" tool pretty quick, but so far, no luck, and I have already been looking for a while.
To me, it seems like a tool that would be useful in tons of scenarios, so I almost can't believe it doesn't exist.
I know about tools such as hbm2java. I know it is possible to create POJOS/orm mapping from a ddl and POJOS/DDL from an orm mapping. But I need the orm mapping given the POJOs.
Also, I know a JPA xml mapping can be pretty short and simple/basic properties are auto mapped. I realize I won't have to map every single property, but still, I am facing a lot of repetitive work if such a tool does not exist.
So, does a "javamodel 2 jpa xml mapping" tool exist?
I created a simple tool for this, hosted at Github: https://github.com/IntegratingStuff/java2jpa
Basic usage example:
Java2JpaMappingGenerator java2JpaMappingGenerator =
new Java2JpaMappingGenerator();
java2JpaMappingGenerator.setRenderJpaMappingForClassStrategy(
new RenderJpaMappingForClassStrategyDefaultImpl());
JpaMappingRendererDefaultImpl jpaMappingRenderer =
new JpaMappingRendererDefaultImpl("target/META-INF/orm.xml");
java2JpaMappingGenerator.setJpaMappingRenderer(jpaMappingRenderer);
java2JpaMappingGenerator.generateJpaMappingsForPackages("com.test.model");
jpaMappingRenderer.createMappedFiles();
With this tool, you can create JPA Xml mappings from a Java POJO domain model. However, often you will need to create a custom implementation of the RenderJpaMappingForClassStrategy interface for you own model in order to use the tool efficiently.
Maybe stupid idea but how about a batch generator creating fasade/proxy .java files with JPA #Annotation tags. Big show stopper might be your app must use JPACustomer type not real one. Just one suggestion don't kill the messenger.
#Entity
#Table(name="customer")
public class JPACustomer extends Customer {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
public long getId() { return super.getId(); }
public void setId(long id) { super.setId(id); }
#Column(name="name")
public String getName() { return super.getName(); }
public void setName(String s) { super.setName(s); }
// ElementCollection provides simple OneToMany linking in OpenJPA.
// joinColumn.name=foreign key column in child table
#ElementCollection(fetch=FetchType.LAZY)
#CollectionTable(name="cust_role", joinColumns={#JoinColumn(name="cust_id")})
#Column(name="role")
public List<String> getRoles() { return super.getRoles(); }
public void setRoles(List<String> roles) { super.setRoles(roles); }
...
}
I would recommend using Eclipse's JPA support (Dali)