I have an Entity for example Employee that contains a #Transient Object Salary which will be derived from a related table/Entity DailyTimeRecord (DTR). DTR object data retrieval uses Joins and it is also autowired in the Employee object. The list of DTR objects will be the basis in computing the value of the Salary Object.
I found here [1]: Why is my Spring #Autowired field null? that using new keyword should be avoided, and let IoC Container create objects. In addition, I want to avoid using new keyword to minimize the coupling of my codes and ensure future compatibility and support scalability as much as possible. Therefore, I have interface Salary and implemented by a SalaryImpl class.
But Each time I tried to run the codes the autowired on a transient attribute Salary, it is always null. And I found the root cause here [2]: How to populate #Transient field in JPA? that Transient will always be null in JPA.
How will I ever create a object that avoiding the use of new keyword while it is a transient attribute?
Entity Class
#Entity
Class Employee implements Serializable {
//Attributes from DB here
#OneToMany
#JoinColumn(name="empNumber", referencedColumnName = "empNumber")
private List<DTR> dtr;
#Autowired
#Transient
private Salary salary;
//getters ang setters here
public double computeSalary(){
}
}
Interface of Salary
public interface Salary {
public double computeSalary(List<Benefit> benefits, List<Deduction> deductions);
}
Base/Implementation class of interface salary
#Service
public class SalaryImpl implements Salary, Serializable {
//other attributes here
//getter and setters
//other methods
#Override
public double computeSalary(List<Benefit> benefits, List<Deduction> deductions){
return 0;
}
}
First, #Transient is from JPA which is nothing to do with Spring .
Second, to be able to let Spring to inject beans into Employee, Employee is also required to be registered as a spring bean. But in realty, you can think that Employee is created using "new" by JPA implementation behind scene. That 's why spring cannot auto wire other beans to it.
If you really need do it, you can use AspectJ to do it as described by the docs.
I personally did not try this approach as you can simply make your SalaryService to accept an Employee as one of its argument to compute his salary, which is much simpler and easy to understand than the AspectJ approach.
public interface SalaryService {
public double computeSalary(Employee employee , List<Benefit> benefits, List<Deduction> deductions);
}
And the client code looks like:
#Service
public class EmployeeService {
#Autowired
private SalaryService salaryService;
#Transactional
public void computeEmployeeSalary(Integer employeeId){
Employee employee = entityManager.find(Employee.class , employeeId);
salaryService.computeSalary(employee, .... ,.....);
}
}
Entity objects are created by JPA implementation (like Hibernate) and not managed by spring.
They're neither Singletons nor Prototypes, so generally speaking, you cannot use Autowiring on properties of entity beans (because Autowiring is something that only can be done on spring beans).
You might be interested to read This SO thread for ideas for some workarounds.
Related
In a DDD-project I'm contributing to, we're seeking for some convenient solutions to map entity objects to domain objects and visa versa.
Developers of this project agreed to fully decouple domain model from data model.
The data layer uses JPA (Hibernate) as persistence technology.
As we all reckon that persistence is an implementation detail in DDD, from a developers' point of view we're all seeking for the most appropriate solution in every aspect of the application.
The biggest concern we're having is when an aggregate, containing a list of entities, is mapped to a JPA entity that in it's turn contains a one-to-many relationship.
Take a look at the example below:
Domain model
public class Product extends Aggregate {
private ProductId productId;
private Set<ProductBacklogItem> backlogItems;
// constructor & methods omitted for brevity
}
public class ProductBacklogItem extends DomainEntity {
private BacklogItemId backlogItemId;
private int ordering;
private ProductId productId;
// constructor & methods omitted for brevity
}
Data model
public class ProductJpaEntity {
private String productId;
#OneToMany
private Set<ProductBacklogItemJpaEntity> backlogItems;
// constructor & methods omitted for brevity
}
public class ProductBacklogItemJpaEntity {
private String backlogItemId;
private int ordering;
private String productId;
// constructor & methods omitted for brevity
}
Repository
public interface ProductRepository {
Product findBy(ProductId productId);
void save(Product product);
}
class ProductJpaRepository implements ProductRepository {
#Override
public Product findBy(ProductId productId) {
ProductJpaEntity entity = // lookup entity by productId
ProductBacklogItemJpaEntity backlogItemEntities = entity.getBacklogItemEntities();
Set<ProductBacklogItem> backlogItems = toBackLogItems(backlogItemEntities);
return new Product(new ProductId(entity.getProductId()), backlogItems);
}
#Override
public void save(Product product) {
ProductJpaEntity entity = // lookup entity by productId
if (entity == null) {
// map Product and ProductBacklogItems to their corresponding entities and save
return;
}
Set<ProductBacklogItem> backlogItems = product.getProductBacklogItems();
// how do we know which backlogItems are: new, deleted or adapted...?
}
}
When a ProductJpaEntity already exists in DB, we need to update everything.
In case of an update, ProductJpaEntity is already available in Hibernate PersistenceContext.
However, we need to figure out which ProductBacklogItems are changed.
More specifically:
ProductBacklogItem could have been added to the Collection
ProductBacklogItem could have been removed from the Collection
Each ProductBacklogItemJpaEntity has a Primary Key pointing to the ProductJpaEntity.
It seems that the only way to detect new or removed ProductBacklogItems is to match them by Primary Key.
However, primary keys don't belong in the domain model...
There's also the possibility to first remove all ProductBacklogItemJpaEntity instances (which are present in DB) of a ProductJpaEntity, flush to DB, create new ProductBacklogItemJpaEntity instances and save them to DB.
This would be a bad solution. Every save of a Product would lead to several delete and insert statements in DB.
Which solution exists to solve this problem without making too many sacrifices on Domain & Data model?
You can let JPA/Hibernate solve problem for you.
public void save(Product product) {
ProductJpaEntity entity = convertToJpa(product);
entityManager.merge(entity);
// I think that actually save(entity) would call merge for you,
// if it notices that this entity already exists in database
}
What this will do is:
It will take your newly created JPA Entity and attach it
It will examine what is in database and update all relations accordingly, with priority given to your created entity (if mappings are set correctly)
This is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
Entity views can also be updatable and/or creatable i.e. support flushing changes back, which can be used as a basis for a DDD design.
Updatable entity views implement dirty state tracking. You can introspect the actual changes or flush changed values.
You can define your updatable entity views as abstract classes to hide "implementation specifics" like e.g. the primary key behind the protected modifier like this:
#UpdatableEntityView
#EntityView(ProductJpaEntity.class)
public abstract class Product extends Aggregate {
#IdMapping
protected abstract ProductId getProductId();
public abstract Set<ProductBacklogItem> getBacklogItems();
}
#UpdatableEntityView
#EntityView(ProductBacklogItemJpaEntity.class)
public abstract class ProductBacklogItem extends DomainEntity {
#IdMapping
protected abstract BacklogItemId getBacklogItemId();
protected abstract ProductId getProductId();
public abstract int getOrdering();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
Product p = entityViewManager.find(entityManager, Product.class, id);
Saving i.e. flushing changes is easy as well
entityViewManager.save(entityManager, product);
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 for flushing changes, you can define a save method in your repository that accepts the updatable entity view
I believe you need to address the issue in a different way.
It is really hard to determine which has been changed when you have a complex graph of objects. However, there should be someone else (maybe a service) which really knows what have changed in advance.
In fact, I did not see in your question the real business "Service" or a class which address the business logic. This will be the one who can solve this issue. As a result, you will have in your repository something more specific removeProductBacklogItem(BacklogItemId idToRemove) or... addProductBacklogItem(ProductId toProductId, ProductBacklogItem itemToAdd). That will force you to manage and identify changes in other way... and the service will be responsible for.
I don't know why Spring doesn't like my code:
I have Entry.java:
#Entity
#Table(name = "entries")
public class Entry {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "text")
private String text;
}
EntryDao.java:
public interface EntryDao extends JpaRepository<Entry, Long> {
List<Entry> findAllEntries();
}
EntryService.java:
#Service
public interface EntryService {
List<Entry> findAllEntries();
}
EntryServiceImpl.java:
public class EntryServiceImpl implements EntryService {
private EntryDao entryDao;
private SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public List<Entry> findAllEntries() {
Session session = this.sessionFactory.getCurrentSession();
List<Entry> entries = session.createQuery("from entries").list();
return entries;
}
}
This code gives me an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entryDao': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property findAllEntries found for type Entry!
I don't understand how to handle this error and why this error occurs.
The root cause you got the exception is that you're against the convention/rules to declare/create queries in Spring Data JPA.
The official docs of Spring Data JPA mentioned that:
The goal of Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.
The central interface of abstraction is Repository, to manage your entity, you need to declare your own interface of Repository and JPA will help you to create proxy instances for those interfaces. There're already some base Repositories like CrudRepository or PagingAndSortingRepository to provide basic functionalities as you can tell from their names, so by extending those basic ones, you'll have many basic methods. To define more specific access methods, you need to follow the ways JPA provided to create queries:
Define method in your interface following the method name convention
Use #Query annotation to define it manually
For the first method, the docs of Query Create has detailed clarification, here's some key idea:
The mechanism strips the prefixes find…By, read…By, query…By, count…By, and get…By from the method and starts parsing the rest of it. The introducing clause can contain further expressions such as a Distinct to set a distinct flag on the query to be created. However, the first By acts as delimiter to indicate the start of the actual criteria. At a very basic level you can define conditions on entity properties and concatenate them with And and Or
Simply speaking, JPA will parse the method name and try to find the related property to create query criteria for you.
Now let's have a look at your code, if you just want to retrieve all of your entities, you don't need to define your own method, there's already findAll methods pre-defined, if you want to retrieve entities based on text content, it's supposed to look like:
Entity findByText(String text)
but your method findAllEntites just don't match any rules, so JPA throws such an error message to you.
As #AbdullahWasi said, just use the existing findAll() method from SpringData for your code. You might want to place a #Transactional annotation in your code, but that depends on your transaction boundaries.
Just remove your custom method from your Dao.
public interface EntryDao extends JpaRepository<Entry, Long> {
}
And use the default spring data findAll
#Transactional
public class EntryServiceImpl implements EntryService {
private EntryDao entryDao;
private SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public List<Entry> findAllEntries() {
return entryDao.findAll();
}
}
How do I avoid having a class and an interface per entity when using JPA with Spring Boot?
I have the following entity (and 10 other):
#Entity
#Table(name = "account")
public class Account {
#Id
#GeneratedValue
private Long id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "password", nullable = false)
private String password;
...
In order to be able to persist this entity, I need to setup an interface per entity:
#Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
}
and then #autowire it:
#Controller
public class AdminController {
#Autowired
AccountRepository accountRepo;
Account account = new Account();
account.setUsername(...);
...
accountRepo.save(account);
If I now have 10 entities, it means that I need to define 10 #Repository interfaces and #autowire each of those 10 interfaces.
How would I embed that save method directly into Account so that I only have to call account.save() and how do I get rid of all those #repository interfaces I have to declare per entity?
Most likely not the answer you like, but I give it to you anyways.
All this interfaces per class seems useless and boilerplate when starting a project, but this changes over time when a project gets larger. There are more and more custom database interactions per entity. Additionally you can also define queries for a group of entities by subclassing the JpaRepository class.
But it is possible to improve the controller sections of your code by declaring a base class handling the repository autowire.
Example how this could be done (requires I think Spring 4)
public class BaseController<Model> {
#Autowired
protected JpaRepository<Model, Long> repository;
}
#Controller
public class AdminController extends BaseController<Admin> {
}
One option, if your entities have some kind of relationship is to use #OneToMany, #OneToOne and friends type annotations. This won't effectively replace all repository interfaces, but might reduce the amount you need. Barring that, you could try the active record pattern. Spring has Spring Roo that has some code generators for this, but I'm admittedly not a big fan of Roo. A quick Google search turned up ActiveJPA which uses the active record style and gives you the benefits you're looking for without the need for Spring Roo, just doesn't look like it's been maintained in a while. https://github.com/ActiveJpa/activejpa
I'm working on an exercise where we're supposed to create a car-rental program in Java where all the data should be stored in a PostgreSQL database using JPA and EclipseLink.
I've managed to create a test-class which connects and stores/reads data to/from the database. Now I'm wondering how I should proceed to make this "big" car-rental program work together with the database...
We've got about 10 classes (Car.java, Customer.java, etc.), which I think based on an earlier example, should be connected to the main/client-classes (Customer_Client.java, Admin_Client.java, etc.) using a Controller-class(?). But I'm not quite sure how and why. If I understand it right, I think the database connecting code etc. is supposed to happen in the main/client-classes?
Could someone which is familiar with this kind of programming/modelling (ORM) point me in the right direction about how the Controller-class should work together with the client-classes?
Based on the earlier example, I guess the Controller-class should contain a getCars, getCustomers etc. method for all the classes I need to access in the main/client-classes?
I'm also wondering how I should add "custom"/class attributes (e.g. Adress.java) as an column in a table in the database? When I'm trying using the same method as with the String and Integers for e.g. the Adress attribute, I get this exception:
"Exception Description: The type [class no.hib.dat101.Adress] for the attribute [adress] on the entity class [class no.hib.dat101.Customer] is not a valid type for a serialized mapping. The attribute type must implement the Serializable interface."
I guess this has something to do with the database table-column only supports certain datatypes?
A controller class in ORM is usually a DAO. DAO is a pattern which defines how to create/read/update/delete objects from database. A general DAO can look like this:
public interface Dao<E> implements Serializable{
public E find(int id);
public void insert(E entity);
public void update(E entity);
public void delete(int id);
}
And its implementation (for example for Car entity) can look like this:
public class CarDao implements Dao<Car>{
private EntityManager em;
public Car find(int id){
return em.find(id, Car.class);
}
public void insert(Car entity){
em.persist(entity);
}
public void update(Car entity){
em.merge(entity);
}
public void delete(int id){
em.delete(find(id));
}
}
For more info about DAO pattern please see Core J2EE Patterns - DAO (loooong but VERY good reading) or this link (shorter reading, but you will get a general idea about DAO faster :))
Entities update/insert is very easy, for example lets say that you want to set a new address for some customer.
private CustomerDao customerDao;
private Addressdao addressDao;
private int customerId;
public void updateCustomerWithAddress(){
Address address = new Address();
//init address variables
addressDao.insert(address);
Customer customer = customerDao.find(customerId);
//I assume you have a bidirectional oneToOne mapping between address and customer
address.setCustomer(customer);
customer.setAddress(address);
customerDao.update(customer);
}
In case of an exception you are getting, it says that your entities does not implement Serializable interface. So maybe by implementing this interface you will fix your issue, but we can really say much without actually seeing the code itself.
Basing on your exception, you should let no.hib.dat101.Adress implement java.util.Serializable so it is marked to serialize when saving a no.hib.dat101.Customer.
I guess this has something to do with the database table-column only supports certain datatypes?
No, your issue is not related with database. How about adding implementsSerializable to your Adress class declaration?
Read about it more here.
I was trying to write a user authentication system in Java. So I wrote some DAO class. First I did write a class named Persistence which is abstract. It is responsible for holding some common attributes. And wrote a class named User extending Persistence class. Those classes are –
public abstract class Persistance {
private Date createdDate;
private Date lastUpdatedDate;
private long version;
private boolean isDeleted;
//getter and setters
}
and the user class
public class User extends Persistance{
private String username;
private String password;
private String passwordConfired;
// getters and setters
}
My questions are- what is the best way to write variable name, which one is good, createdDate or dateCreated, deleted or isDeleted etc.
And is this approach is okay or is there more good approach ?
And how to implement data versioning?
To write a DAO, typically you create an interface that defines the behavior of the DAO.
interface MyObjDao {
public int save(MyObj myObj);
public void delete (MyObj myObj);
// as many methods as you need for data acess
}
and then you create the actual implementation
class MyObjDaoImpl implements MyObjDao {
// implement methods here
}
The advantages of this are:
1) Because you define an interface, mocking DAOs is easy for any testing framework
2) The behavior is not tied to an implementation -- your DAOImpl could use jdbc, hibernate, whatever
Your Persistance class is really a base class for all entities -- i.e. all classes instances of which get saved, where you want to represent some common fields in one place. This is a good practice -- I wouldn't call the class Persistance, something like BaseEntity is better (IMHO). Be sure to have javadocs that explain the purpose of the class.
With respect to variable names, as long as they make sense and describe what they are for, its good.
so dateCreated or createdDate are both fine; they both get the idea across.
You are mixing a DAO (data access object) and a VO (value object) - also known as a DTO (data transfer object) - in the same class.
Example using an interface for DAO behavior (blammy and kpow might be webservice, oracle database, mysql database, hibernate, or anything meaningful):
public interface UserDTO
{
boolean deleteUser(String userId);
UserVO readUser(String userId);
void updateUser(String userId, UserVO newValues);
}
package blah.blammy;
public class UserDTOImpl implements UserDTO
{
... implement it based on blammy.
}
package blah.kpow;
public class UserDTOImpl implements UserDTO
{
... implement it based on kpow.
}
Example VO:
public class UserVO
{
String firstName;
String lastName;
String middleInitial;
... getters and setters.
}
I prefer to identify the target of the delete using an ID instead of a VO object. Also, it is possible that an update will change the target identified by user ID "smackdown" to have user ID "smackup", so I generally pass an id and a VO.
A good approach would be to use JPA with all of its features, this tutorial was really helpful.
It explains how to use the #PrePersist and #PreUpdate annotations for setting create and update timestamps. Optimistic locking is supported by the #Version annotation.
My questions are- what is the best way to write variable name, which
one is good, createdDate or dateCreated, deleted or isDeleted etc.
createdDate or dateCreated is very subjective. In databases, I have mostly seen createdDate though. Between deleted and isDeleted, I prefer (again subjective) deleted. I think the getter method can be named isDeleted().