Create multiple beans of the same Class in a dynamic and lazy manner - spring

#ConfigurationProperties("person")
public class PersonConfiguration {
private List<Details> details = new ArrayList<>();
//getters and setters and tostring
public static class Details {
private String key;
private String company;
private String family;
//getters and setters and tostring
}
}
public class Person {
public String key;
public SomeClass obj;
//constructor
//getter, setter and tostring
}
#Component
public class PersonFactory {
#Autowired
PersonConfiguration personConfig;
public Person getPerson(String key) {
//if key exists in PersonConfiguration
//create SomeClass based on family and compnay details for corresponding key
//create Person bean using key and SomeClass.
}
}
How can i create multiple beans of Person in the above class in lazy manner only when requested based on the different keys in the request.
Basically have a configuration and factory class. Based on an incoming request need to check if it exists in the configuration and if it does, need to create an object of some type using factory class.

Related

How to exclude/disable #Entity Annotation for particular class

I want to disable #Entity Annotation for particular class.
Here is my sample code.
#Component
public class GenericDropDown{
private Integer id;
private String key;
private String value;
// Standard getter and setter
The above class is used for fetching data from multiple table for rendering different dropdown list from different tables.
How I can achieve this without #Entity Annotation
Here is my sample code.
#Component
public class GenericDropDown{
private Integer id;
private String key;
private String value;
// Standard getter and setter
#Repository
public class DropDownDao {
#Autowired
private EntityManager entityManager;
public Object runNativeQuery() {
#SuppressWarnings("unchecked")
List<Priority> o= entityManager.createNativeQuery("select Id,PRKEY,PRVALUE from Priority",Priority.class)
.getResultList();
return o;
}
}
**Error:**Unknown entity: com.min.test.Project.entity.Priority; nested exception is org.hibernate.MappingException: Unknown entity: com.min.test.Project.entity.Priority
You can select List of Objects array and map them yourself.
List<Object[]> o = entityManager.createNativeQuery("select Id,PRKEY,PRVALUE from Priority").getResltList();
List<MyClass> result = o.stream().map(arr -> new MyClass((Long) arr[0], (String) arr[1])).collect(Collectors.toList());
Or you also can use a JdbcTemplate instead of EntityManager:
#Autowired
private JdbcTemplate jdbcTemplate;
public List<MyClass> runQuery() {
String select = "select Id,yourParameterHere from Priority";
return jdbcTemplate.query(select, (rs, rowNum) -> new MyClass(rs.getLong("Id"), rs.getString("yourParameterHere")));
}

How to do a Findby In Springboot Mongo repository for Nested Objects

Need your help here in a Spring Data CrudRepository on how to do a findby of nested fields.
My class is of following structure and I need to query using truckId which is of the nested objects
#Document(collection = "unt-truck")
public class TruckModelDTO {
private String type;
private TestDTO testDTO;
}
Class TestDTO.java
public class TestDTO{
private TruckDTO truckDTO;
Private String version;
}
Class TruckDTO.java
public class TruckDTO {
private String truckId;
private String legacySystem;
}
Class TruckRepository.java
#Repository
public interface TruckRepository extends MongoRepository<TruckModelDTO, String> {
// TruckModelDTO findByTruckId(String truckid);
}
So how should I use findby for truckId which is inside a nested class?
You can use with either Entity or DTO as response. but you have to mention the relation between two or three Entity based on you requirement.
I have created Entity. you have to create DTO with same based on entity then apply main DTO as return type in JPA Repository query.
1.Entity
#Entity
public class TruckModel {
private String type;
// mention the relation based on your requirement
private Test test;
}
Entity
#Entity
public class Test {
// here mention the relation based on you requirement
private Truck truck;
Private String version;
}
3.Entity
#Entity
public class Truck {
private String truckId;
private String legacySystem;
}
Repository
#Repository
public interface TruckModelRepository extends MongoRepository<TruckModel, String> {
TruckModelDTO findByTestTruckTruckId(String truckid);
}

Polymorphism example in Spring Boot. How to access methods of implementation class with the bean of the interface?

EDIT : If i declare all the variables in my interface they should be public by default, which opposes encapsulation and i know that i can go with abstract class instead of interface. But, in my question the main point is focused on Spring dependency injection, how can i get an object of the implementation class to access its own methods, i have used #Qualifier but it doesn't seem to work.
I have an interface with the name Account and its two implementation classes SavingsAccount and SalaryAccount. A customer class linking account details with customer with the help of an account object defined in customer class. Please go through the example for a better understanding.
My question is how to access the methods of SavingsAccount in Customer class with the spring bean of the SavingsAccount which is autowired.
If I hardcode something like SavingsAccount sa = new Savingsccount(); in the customer class i can achieve accessing the methods of the SavingsAccount class. In spring i have to do that using #Autowiredand #Qualifier annotation.
#Autowired
#Qualifier("savingsAccount")
private Account account;
But i cannot access the methods of the savingsAccount with the spring bean account.getAccNum();, like it is done with sa.getAccNum;
The complete example:
public interface Account {
public double showFunds();}
#Component
public class SalaryAccount implements Account {
private long accNum;
private double funds;
// getter setter methods
#Override
public double showFunds() {
return funds;
}
}
#Component
public class SavingsAccount implements Account {
private long accNum;
private double funds;
// getter setter methods
#Override
public double showFunds() {
return funds;
}
}
I have used autowired annotation along with qualifier, so that i get a spring bean of the implementation class specified in the #Qualifier
#Component
public class Customer {
private int id;
private String name;
private long mobile;
#Autowired
#Qualifier("savingsAccount")
private Account account;
public Customer() {
super();
}
public Customer(int id, String name, long mobile, Account account) {
super();
this.id = id;
this.name = name;
this.mobile = mobile;
this.account = account;
}
//getters and setters
public void customerAccountProfile(){
// here if i want to access members and variables of Savingsaccount with the bean account. How?
account.getAccNum() ;// throws error
account.showFunds();// works fine beacause it is defined in the interface Account
System.out.println("do nothing");
}
}
You need to add all variables and methods in interface for access as below:
public interface Account {
long accNum;
double showFunds();
}
I couldn't see any proper answer yet, so I am posting this so it might help people in the future.
Solution: I think in the #Component on the SavingsAccount class, you can use the bean name. Like here, you can use #Component("savingsAccount"). And then pass it with the #Qualifier annotation in the Customer class.

Multiple JPA Repositories with multiple Entity Mapping conflict

I am creating a simple one to many relationship using JPA and Spring Data Rest. But i am getting this error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'designationRepository' defined in com.example.relational.BootRelations.repository.DesignationRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.example.relational.BootRelations.models.Designation
That is because I have #Entity classes like Designation and Employee, the code follows like:
#Entity
public class Designation {
private String Designation;
private float Salary;
#OneToMany(targetEntity=Employee.class, mappedBy="designation", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn(name="Emp_Id")
private Set<Employee> employee;
// Getter & Setter and Constructors
}
Now Employee class:
#Entity
#Table(name="Employee")
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="Emp_Id")
private int Emp_Id;
#Column(name="Emp_Name")
private String Emp_Name;
#Column(name="Emp_Email")
private String Emp_Email;
#OneToOne(targetEntity=Designation.class, mappedBy="employee", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private Designation designation;
// // Getter & Setter and Constructors
}
The repositories are:
public interface DesignationRepository extends JpaRepository<Designation, Integer> {}
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {}
Services:
#Service
public class DesignationServiceImpl implements DesignationService {
private DesignationRepository designationRepository;
#Autowired
public DesignationServiceImpl(DesignationRepository designationRepository) {
this.designationRepository = designationRepository;
}
#Override
public List<Designation> findAllDesignation() {
return designationRepository.findAll();
}
}
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeRepository employeeRepository;
#Autowired
public EmployeeServiceImpl(#Qualifier("employeeJPAImpl") EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
}
#Service
public class DesignationServiceImpl implements DesignationService {
private DesignationRepository designationRepository;
#Autowired
public DesignationServiceImpl(#Qualifier("DesignationRepository") DesignationRepository designationRepository) {
this.designationRepository = designationRepository;
}
#Override
public List<Designation> findAllDesignation() {
return designationRepository.findAll();
}
}
As I had two entities I had two controllers:
#RestController
#RequestMapping("/api")
public class DesignationController {
private DesignationService designationService;
#Autowired
public DesignationController(DesignationService designationService) {
this.designationService = designationService;
}
#GetMapping("/designation")
public List<Designation> getAllDesignation(){
return designationService.findAllDesignation();
}
}
and
#RestController
#RequestMapping("/api")
public class EmployeeController {
private EmployeeService employeeService;
#Autowired
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
// Mappings
}
Can anyone help me solve this issue? Until I had one entity it was working fine; as soon as I added another one it failed to start, with the error. Please help me fix the issue.
In Employee class make this changes.
#Entity
#Table
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Long empId;
#Column
private String Name;
#Column
private String Email;
#OneToMany(targetEntity=Designation.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private Designation designation;
// // Getter & Setter and Constructors
}
In the Designation class, make this changes..
#Entity
public class Designation {
#Id
private Long id;
private String role;
private float salary;
#ManyToOne(targetEntity=Employee.class, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn
private Set<Employee> employee;
// Getter & Setter and Constructors
}
This will result in a table structure like this.
Employee
EMP_ID
NAME
EMAIL
Designation
ID
ROLE
SALARY
EMPLOYEE_ID
In OneToMany and ManyToOne association, we must keep a note that, which class is holding the Many side. That side is known as the owning side. As that class will contain the foreign key. Here, our designation class is containing the Many side. So, it will create a foreign key automatically.
If we give the #JoinColumn in the Employee class. Still we will get the Designation class as the Owning class.
You can refer this article, for more details.
Rather than this, let me tell you some of your major mistakes.
Do not give the variables name same as your class name.
By writing variables name as empId in java file, it will result EMP_ID in database.
If a column name or a table name is same your variable name, you can avoid re-mentioning it.
means, if my entity class name is Employee. And I want my database Table name should also be EMPLOYEE. I can avoid specifying #Table(name="EMPLOYEE").
I hope it would be helpful !!

Spring: Method Injection Lookup How to use it?

Can I use Method Injection Lookup -- with a entity class?.I use Spring+JPA+Hibernate. This allow to inject a prototype bean into a singleton bean.Is this also possible with entity beans?A is prototype scoped bean.I want to put A(#Entity) into a class B (ex. DAO) with scope=singleton.Thanks
#Entity
public class A(){
private String name;
private String surname;
...//get and set
}//A
public interface DAO{
public void method();
}//DAO
public class DAOImpl implements DAO{
private A object_a;
public void method(){
//In this method I use everytime a new istance of A
}//method
}//DAOImpl
You can use #Embedded to include your sub bean, and use in your sql.
#Entity
public class User(){
private String name;
#Embedded
private Address address;
#Bean(scope=DefaultScopes.PROTOTYPE)
public User() {
}
...//get and set
}
#Entity
public class Address(){
private String name;
...//get and set
}
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "select u from users u where u.address.name = :addressName")
List<Blog> findUserByAddress(#Param("addressName") String addressName);
}

Resources