MapStruct equivalent of hint(Dozer)? - mapstruct

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

Related

Spring Data Jpa Query methods are not invoking the repositoryBaseClass

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

Autofac - One interface, multiple implementations

Single interface: IDoSomething {...}
Two classes implement that interface:
ClassA : IDoSomething {...}
ClassB : IDoSomething {...}
One class uses any of those classes.
public class DummyClass(IDoSomething doSomething) {...}
code without Autofac:
{
....
IDoSomething myProperty;
if (type == "A")
myProperty = new DummyClass (new ClassA());
else
myProperty = new DummyClass (new ClassB());
myProperty.CallSomeMethod();
....
}
Is it possible to implement something like that using Autofac?
Thanks in advance,
What you are looking for is, as I remember, the Strategy Pattern. You may have N implementations of a single interface. As long you register them all, Autofac or any other DI framework should provide them all.
One of the options would be to create a declaration of the property with private setter or only getter inside Interface then implement that property in each of the class. In the class where you need to select the correct implementation, the constructor should have the parameter IEnumerable<ICommon>.
Autofac or any other DI frameworks should inject all possible implementation. After that, you could spin foreach and search for the desired property.
It may look something like this.
public interface ICommon{
string Identifier{get;}
void commonAction();
}
public class A: ICommon{
public string Identifier { get{return "ClassA";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class A: ICommon{
public string Identifier { get{return "ClassB";} }
public void commonAction()
{
Console.WriteLine("ClassA");
}
}
public class Action{
private IEnumerable<ICommon> _common;
public Action(IEnumerable<ICommon> common){
_common = common;
}
public void SelectorMethod(){
foreach(var classes in _common){
if(classes.Identifier == "ClassA"){
classes.commonAction();
}
}
}
}

How is entities inheritance implemented in Spring data mongodb

I've two entities Person, Employee and Employee1. I want to implement entities inheritance in Spring Data MongoDB. Like in Spring Data JPA, what are the equivalent annotations for #Inheritance and #PrimaryKeyJoinColumn in Spring Data MongoDB. Right now, I've implemented something like this:
interface Person {
String getId();
void setId(String id);
String getName();
void getName(String name);
}
#Document(collection = "person")
class PersonImpl implements Person {
#Id
String id;
// Getters and setters
// Constructors, equals, hashcode and toString methods
}
interface Employee extends Person {
int getNumberOfDependents();
void getNumberOfDependents(int numberOfDependents);
}
#Document(collection = "employee")
class EmployeeImpl extends PersonImpl implements Employee {
// Getters and setters
// Constructors, equals, hashcode and toString methods
}
interface Employee1 extends Person {
int getNumberOfDependents();
void getNumberOfDependents(int numberOfDependents);
}
#Document(collection = "employee1")
class Employee1Impl extends PersonImpl implements Employee1 {
// Getters and setters
// Constructors, equals, hashcode and toString methods
}
Repository structure:
public interface PersonRepository extends MongoRepository<Person, String> {
}
public interface EmployeeRepository extends MongoRepository<Employee, String> {
}
public interface Employee1Repository extends MongoRepository<Employee1, String> {
}
I'm saving the Person object first and then taking the ID of it and creating an Employee object with the same ID and saving it. This creates new object and hence I'm losing all the Person object stuff.
I also feel that I've to get the NoRepositoryBean implemented also.
I'm confused. Please help.
Here is one approach:
#Document(collection = "person")
class Person {
#Id
String id;
// Getters and setters
// Constructors, equals, hashcode and toString methods
}
Note that the collection field refers to "person" and not to "employee"
#Document(collection = "person")
class Employee extends Person {
String jobTitle;
// Getters and setters
// Constructors, equals, hashcode and toString methods
}
In this method you do not need to create a repository for each derived class
#Repository
public interface PersonRepository extends MongoRepository<Person, String> {}
Code example:
#Autowired
private PersonRepository personRepo;
public void test() {
Employee employee = new Employee("1", "teacher")
personRepo.save(employee)
Optional<Person> optionalPerson = personRepo.findById("1");
Employee employeeFromDb;
if (optionalPerson.isPresent()) {
employeeFromDb = (Employee)optionalPerson.get()
}
else {
// could not find in db
}
}
if you want to find all employees you should have a methode on MongoRepository
called
List<Employee> findAll();

Any way to reference an attribute of a parameter in the query?

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);
}

Inner classes as spring-data-repositories

It seems that spring-data only constructs repositories for interfaces that are defined at the top level. For example
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {
}
works great but if i embed it into a class for example
public class Repositories {
public static interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {
}
}
i cannot find any documentation on such a restriction. So my question is: Is it possible to define spring-data-repositories as inner-classes?
You should set the considerNestedRepositories boolean to true.