I have a repository base class as defined below.
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
}
public class BaseRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInfo, EntityManager entityMgr) {
super(entityInfo, entityMgr);
}
// ...
}
#Configuration
#EnableJpaRepositories(basePackages = "org.example",
repositoryBaseClass = BaseRepositoryImpl.class)
public class BaseConfig {
// additional JPA Configuration
}
I have defined a business repository class and a query method as seen below.
#Repository
public interface CarRepository extends BaseRepository<Car, Long> {
#Query("SELECT c FROM Car c Where active = 1")
List<Car> findAllActiveCars();
}
I have a test class which invokes the findAllActiveCars(). I am getting the expected results. But, that query method is not invoking any of the methods in BaseRepository class. How to customize the return values of the query methods?
You didn't show the methods that you did implement, so it is not clear why they don't get called, but since you want to decrypt entity fields, consider listening to JPAs entity lifecycle events. #PostLoad should be able to do the trick.
https://docs.jboss.org/hibernate/core/4.0/hem/en-US/html/listeners.html
Related
In Dozer we are able to mention interfaces in hint during field mapping. How can we achieve the same in MapStruct ?
I could not put the exact code here. But, it is the similar as below.
We have here an Domain class example:
Class A<T extends B> extends C<T>
{
...
};
Where,
B is a abstract class.
C is a class which contains a List item which we have to map.
Similar is the structure of the classes and interfaces on DTO side.
So, the mapping is as below in Dozer:
<mapping>
<class-a>Domain.A</class-a>
<class-b>DTO.A</class-b>
<field>
<a>item</a>
<b>item</b>
<a-hint>Domain.B</a-hint>
<b-hint>DTO.B</b-hint>
</field>
</mapping>
In MapStruct how do we refer the interfaces as given in the hint in Dozer ?
Scenario:
We have:
public class ShopList<T extends Inp> extends Shop<T>\
{ ... };
where,
Inp is a abstract class with no fields in it like:
public abstract class Inp() { };
Shop is a class like:
public class Shop<T extends ShopInp> implements Serializbale
{ private List<T> items = new ArrayList<T>();
//getters and setters for the items };
ShopInp is a public interface with no fields in it like:
public interface ShopInp {} .
We have similar structure of classes on DTO side and Domain side.
Could you please let me know how would the mapper look like for the above scenario ?
In general, If we try mapping the ShopList class, then, how do we ensure that the T extends ShopInp and T extends Inp are also being mapped as a part of ShopList?
So called hints can be used via BeanMapping#resultType. MapStruct can use that to create the instance of the object you are trying to map. However, it will only create mapping for the elements of the abstract class, as it has no other information during compilation time (Dozer uses reflection and can detect the fields of the type during runtime).
Imagine you have this structure
public interface Fruit {
String getName();
String setName(String name);
}
public Apple implements Fruit {
...
}
public Banana implements Fruit {
...
}
public abstract class FruitDto {
private String name;
//getters and setters
}
public AppleDto extends FruitDto {
...
}
public BananaDto extends FruitDto {
...
}
public class Basket {
private Collection<Fruit> fruits;
}
public class BasketDto {
private Collection<FruitDto> fruits;
}
Your mapper can then look like:
#Mapper
public interface BasketMapper {
BasketDto map(Basket basket);
#BeanMapping(resultType = BananaDto.class)
FruitDto map(Fruit fruit);
}
Using this mapper all fruits in the BasketDto would be of an instance BananaDto (due to the BeanMapping#resultType and mapping would only be created for the elements of the FruitDto
First of all, this is not a duplicate of Spring Data: Override save method. I want to override the save method, and I know where to find the documentation, but my question is how to call the original implementation in my custom code.
To override save() method in spring-data-*, you do something like below:
interface CustomizedSave<T> {
<S extends T> S save(S entity);
}
class CustomizedSaveImpl<T> implements CustomizedSave<T> {
public <S extends T> S save(S entity) {
// Your custom implementation
}
}
interface UserRepository extends CrudRepository<User, Long>, CustomizedSave<User> {
}
interface PersonRepository extends CrudRepository<Person, Long>, CustomizedSave<Person> {
}
My question is how to call the "super" implementation of save()? In spring-data-elasticsearch, the default save() implementation is not so simple to set up (basically I need to copy AbstractElasticsearchRepository source code), so I would rather not do this.
#Autowired
private EntityManager em;
#Override
public User save(User entity) {
JpaRepositoryFactory jrf = new JpaRepositoryFactory(em);
UserRepositories repoWithoutCustom = jrf.getRepository(UserRepositories.class);
do somth....
}
Where repoWithoutCustom what you need, your UserRepository without any customized methods. Just use required RepositoryFactory, in your case Elastic as i understood
Is there any way to reference an attribute of a parameter that is part of a query for a JPA repository?
My sample is
#Entity
public class Matchday implements Serializable {
#Id
private int matchdayNumber;
//..
//setters and getters defined
//..
//hashCode and equals methods overridden
}
public interface MyRepository extends JpaRepository<Matchday, Integer> {
#Query("... WHERE t.matchday.matchdayNumber < :matchday.matchdayNumber - 1;")
public findByCriteria(Matchday matchday);
}
The construction :matchday.matchdayNumber does not seem to be a valid syntax. Is there any other way to do it than passing the int value for matchdayNumber instead of a reference to Matchday object to this method?
Looks like this is possible with Spring JPA Data which allows SpEL in queries.
public interface MyRepository extends JpaRepository<Matchday, Integer> {
#Query("... WHERE t.matchday.matchdayNumber < :#{#matchday.matchdayNumber - 1}")
public findByCriteria(Matchday matchday);
}
Am successfully injecting jpa repositories using CDI. I wanted to add custom behaviour(soft deletes) to all repositories. When using spring I can enable customer behaviour by specifying the repository base class
#EnableJpaRepositories(repositoryBaseClass = StagedRepositoryImpl.class)
How do I specify the same in CDI? Thanks in advance.
To add custom behaviour to Jpa Repositories(in your case for delete),
1. Create a base repository like below:
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
#Override
default void delete(T entity){
// your implementation
}
}
2. Now inherit Jpa Repositories from custom repository(i.e BaseRepository) like below:
public interface EmployeeRepository extends BaseRepository<Employee, Long> {
}
3. Inject your repository into Service class and call the delete method.
#Service
class EmployeeService {
#Inject
private EmployeeRepository employeeRepository;
public void delete(Long id) {
employeeRepository.delete(id);
}
}
Now whenever you call delete on repositories which are child of BaseRepository, your custom implementation for delete will be invoked.
Here is the way to add custom logic to your repositories:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
Basically you create a custom repository named {YourRepositoryName}Custom
interface UserRepositoryCustom {
public void someCustomMethod(User user);
}
And implement it:
class UserRepositoryImpl implements UserRepositoryCustom {
public void someCustomMethod(User user) {
// Your custom implementation
}
}
Your main repository should extend the custom one.
Hope this helps!
Our project involves hundreds of tables/entities, so it's boring to create a single repository for every entity. We want to create a generic repository for common query use which might have a below look:
#Repository
public interface GenericRepo extends JpaRepository<Ctmpdis,Integer> {
public List findByQl(String jpql,Map params);
}
I want to pass concrete jpql to the method on the fly so that we don't have to create so many repos just need one to do all the variable queries.The problem of this idea is I don't know how to pass a query to repo and make it work. Does anybody know how to do it and is it possible? Thanks
You could implement a custom repository, here is an example
public interface MyRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
public List findByQl(String jpql,Map params);
}
public class MyRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
#PersistenceContext
private EntityManager entityManager;
public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
}
public List findByQl(String jpql,Map params) {
// implementation goes here
}
}