#Access annotation
i'm confused how this annotation works. I know by default, the access type is defined by the place where we put the identifier annotation (#Id).
If we put it on the field – it will be AccessType.FIELD,
if we put it on the getter – it will be AccessType.PROPERTY.
This is my entity
#Entity
public class Student {
#Id
#GeneratedValue
private Long ID;
private String firstName;
#Access(value= AccessType.PROPERTY)
private String lastName;
public String getFirstName() {
System.out.println("~~~~~~~~getFirstName~~~~~~~~~");
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = "FirstName: " + firstName;
System.out.println("~~~~~~~~setFirstName~~~~~~~~~");
}
public String getlastName() {
System.out.println("~~~~~~~~getlastName~~~~~~~~~");
return lastName;
}
public void setLastName(String lastName) {
this.lastName = "LastName: "+ lastName;
System.out.println("~~~~~~~~setLastname~~~~~~~~~");
}
}
I add to the Setter prefix ("FirstName: " and "LastName: ") to check if it will be called.
As i have #Id on the field that's means AccessType.FIELD, but i change it in lastName to AccessType.PROPERTY.
As i understood on this case JPA should save to the database firstName field without prefix but lastName with (because it will call setter setLastName)
I'm not sure that i understand how to use this on project and how to check if it works. I want to write a test to prove it but i don't know how to implement this. can you please help me. I want to prove that JPA does not call Getter/Setter to firstName and call it for lastName fields.
This is my test without implementation
class StudentTest {
private EntityManagerFactory entityManagerFactory;
private EntityManager entityManager;
#BeforeEach
public void init() {
entityManagerFactory = Persistence.createEntityManagerFactory( "in.memory.test");
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
}
#AfterEach
public void destroy() {
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
}
#Test
public void studentFirstName(){
}
#Test
public void studentLastName(){
}
}
I suppose that you can write something like this:
`
#Test
public void testAccessAnnotation() {
// Create a new instance of the Student entity
Student student = new Student();
student.setFirstName("John");
student.setLastName("Doe");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(student);
entityManager.getTransaction().commit();
entityManager.clear();
TypedQuery<Student> query = entityManager.createQuery("SELECT s FROM Student s WHERE s.ID = :id", Student.class);
query.setParameter("id", student.getID());
student = query.getSingleResult();
assertEquals("John", student.getFirstName());
assertEquals("LastName: Doe", student.getLastName());
}
`
Related
I've this Java application in package com.luv2code.hibernate.demo:
package com.luv2code.hibernate.demo;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.luv2code.hibernate.demo.entity.Employee;
public class CreateEmployeeDemo {
public static void main(String[] args) {
// create session factory
SessionFactory factory = new Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Employee.class)
.buildSessionFactory();
// create a session
Session session = factory.getCurrentSession();
try {
// create the employee object
System.out.println("Creating a new employee object...");
Employee tempEmployee = new Employee("John", "Doe", "Doe Corp.");
// start a transaction
session.beginTransaction();
// save the employee object
System.out.println("Saving the employee...");
session.save(tempEmployee);
// commit the transaction
session.getTransaction().commit();
// find the employee's ID: primary key
System.out.println("Save employee. Generated ID: " + tempEmployee.getId());
// now get a new session and start transaction
session = factory.getCurrentSession();
session.beginTransaction();
// retrieve employee based on the ID: primary key
System.out.println("\nGettin employee with id: " + tempEmployee.getId());
Employee myEmployee = session.get(Employee.class, tempEmployee.getId());
System.out.println("Get complete: " + myEmployee);
// commit the transaction
session.getTransaction().commit();
// delete student id=2
System.out.println("Deleting student id=2");
session.createQuery("delete from Student where id = '2'").executeUpdate();
// commit the transaction
session.getTransaction().commit();
System.out.println("Done!");
}
finally {
factory.close();
}
}
}
It uses this Employee class in package com.luv2code.hibernate.demo.entity:
package com.luv2code.hibernate.demo.entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="company")
private String company;
public Employee() {
}
public Employee(String firstName, String lastName, String company) {
this.firstName = firstName;
this.lastName = lastName;
this.company = company;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
#Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", company=" + company + "]";
}
}
When I run the program I get this error:
Saving the employee...
Jul 17, 2020 6:46:40 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/hb_student_tracker?useSSL=false&serverTimezone=UTC]
Jul 17, 2020 6:46:40 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections close
ERROR: Connection leak detected: there are 1 unclosed connections upon shutting down pool jdbc:mysql://localhost:3306/hb_student_tracker?useSSL=false&serverTimezone=UTC
Exception in thread "main" org.hibernate.MappingException: Unknown entity: com.luv2code.hibernate.demo.entity.Employee
at org.hibernate.metamodel.internal.MetamodelImpl.entityPersister(MetamodelImpl.java:704)
at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1606)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:114)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:634)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:627)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:622)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:351)
at com.sun.proxy.$Proxy25.save(Unknown Source)
at com.luv2code.hibernate.demo.CreateEmployeeDemo.main(CreateEmployeeDemo.java:33)
I can't see what could be wrong here. It seems to be a mapping exception but I think my mappings should be correct. Can anybody spot the issue?
Use #Entity and #Table for map database table name with Employee class
#Entity
#Table(name = "employee")
public class Employee { ... }
i am writing a web application(server based application) where i am having a dao layer, the service layer and the application layer. how should i take over the lazy initialization exception, caused due to the fact that entity returned from dao layer is concerned with the session opened inside the method from where it is returned and also closed there which makes the entity detached.
Next thing is it safe to share the hibernate entities across different layer. what makes me to ask this question is the scenario: for example suppose i am having a hibernate entity having one to one association with some other entity. and suppose dao passed it to the service layer to the application layer. now if i try to get this associated entity in application layer through the passed entity getter method, a database query is fired which i think is messing up with the "seperation of concerns" as database related operation should be constrained to the dao layer. am i right?
i have discovered the mentioned problem during the time i am unit testing my dao layer through in-memory database. My scenario is, i am having one of the pojo class called RegisteredUser having the fields: (id, username, firstname, lastname, passwHash, email, StudyCentre). StudyCentre is an another entity which is assosciated with RegistereUser by one to one mapping and username is the naturalid.
What i want is 2 types of read operation, first one is i need to get user details without studycentre through natural id and second one is getting the complete user fields again through naturalid. is making two seperate DTOs a good idea here and passing them across layers.
RegisteredUser Entity:
package com.ignoubadhega.pojos;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.NaturalId;
#Entity
#Table(name = "registered_user")
#DynamicUpdate
public class RegisteredUser {
private Long dbUserId;
private String userName;
private String passwHash;
private String firstName;
private String lastName;
private String email;
private StudyCentre studyCentre;
RegisteredUser() {
}
public RegisteredUser(
String userName, String passwHash, String firstName,
String lastName, String email
) {
super();
this.userName = userName;
this.passwHash = passwHash;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "db_user_id")
public Long getDbUserId() {
return dbUserId;
}
#Override
public String toString() {
return "RegisteredUser [dbUserId="
+ dbUserId
+ ", userName="
+ userName
+ ", passwHash="
+ passwHash
+ ", firstName="
+ firstName
+ ", lastName="
+ lastName
+ ", email="
+ email
+ "]";
}
public void setDbUserId(Long dbUserId) {
this.dbUserId = dbUserId;
}
#Column(name = "username", nullable = false, unique = true)
#NaturalId
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
#Column(name = "passw_hash", nullable = false)
public String getPasswHash() {
return passwHash;
}
public void setPasswHash(String passwHash) {
this.passwHash = passwHash;
}
#Column(name = "first_name", nullable = false)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "last_name", nullable = false)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "email", nullable = false, unique = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "db_study_centre_id", nullable = false)
public StudyCentre getStudyCentre() {
return studyCentre;
}
public void setStudyCentre(StudyCentre studyCentre) {
this.studyCentre = studyCentre;
}
}
Dao Implementor:
package com.ignoubadhega.dao.impl;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.ignoubadhega.dao.RegisteredUserDAO;
import com.ignoubadhega.pojos.RegisteredUser;
public class RegisteredUserDAOImpl implements RegisteredUserDAO {
private SessionFactory sessionFactory;
public RegisteredUserDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void addUser(RegisteredUser user) {
try (Session session = sessionFactory
.openSession()) {
session.beginTransaction();
session.persist(user);
session.getTransaction().commit();
} catch (HibernateException except) {
except.printStackTrace();
}
}
#Override
public RegisteredUser getUserByUserName(String username, boolean doesStudyCentereNeeded) {
try (Session session = sessionFactory
.openSession()) {
RegisteredUser user = session
.bySimpleNaturalId(RegisteredUser.class).load(username);
if (doesStudyCentereNeeded) {
user.setStudyCentre(user.getStudyCentre());
}
return user;
} catch (HibernateException except) {
except.printStackTrace();
}
return null;
}
#Override
public void deleteUser(RegisteredUser user) {
try (Session session = sessionFactory
.openSession()) {
session.beginTransaction();
session.delete(user);
session.getTransaction().commit();
} catch (HibernateException except) {
except.printStackTrace();
}
}
#Override
public void updateUser(RegisteredUser user) {
try (Session session = sessionFactory
.openSession()) {
session.beginTransaction();
session.update(user);
session.getTransaction().commit();
} catch (HibernateException except) {
except.printStackTrace();
}
}
}
TestCase which finds the problem of lazy initalization:
#Test
#DisplayName(
"User through its natural id 'username' assuming the user"
+ " is persistent in the database is successful"
)
void test_fetching_a_persistent_user_through_username_is_successful() {
try (Session session = sessionFactory.openSession()) {
session.beginTransaction();
session.persist(user);
session.getTransaction().commit();
RegisteredUser retrievedUser =
dao.getUserByUserName("prav", true);
assertNotNull(retrievedUser);
assert_actual_user_and_retrieved_user_fields_are_equal(user,
retrievedUser);
} catch (HibernateException except) {
except.printStackTrace();
}
}
private static void assert_actual_user_and_retrieved_user_fields_are_equal(
RegisteredUser actualUser, RegisteredUser userRetrieved
) throws MultipleFailuresError {
assertAll("user fields",
() -> assertEquals(actualUser.getUserName(),
userRetrieved.getUserName()),
() -> assertEquals(actualUser.getPasswHash(),
userRetrieved.getPasswHash()),
() -> assertEquals(actualUser.getFirstName(),
userRetrieved.getFirstName()),
() -> assertEquals(actualUser.getLastName(),
userRetrieved.getLastName()),
() -> assertEquals(actualUser.getEmail(),
userRetrieved.getEmail()),
() -> {
StudyCentre retrievedCentre =
userRetrieved.getStudyCentre();
assertNotNull(retrievedCentre);
assertAll("user study centre assosciated",
() -> assertEquals(
actualUser.getStudyCentre().getData()
.getStudyCentreName(),
retrievedCentre.getData()
.getStudyCentreName()),
() -> assertEquals(
actualUser.getStudyCentre().getData()
.getRegionalCentreCode(),
retrievedCentre.getData()
.getRegionalCentreCode()));
});
}
i want to keep my service layer(not yet implemented) to be isolated from things specific to hibernate like sessions and database related operations(CRUD). how can i achieve it. is there any design patterns i should follow. i am new to hibernate. please guide me if i am doing something wrong any where. i have tried finding the similar threads on google but failed to get any insights about the issue.
how should i take over the lazy initialization exception, caused due to the fact that entity returned from dao layer is concerned with the session opened inside the method from where it is returned and also closed there which makes the entity detached.
You would deal with that by opening and closing the session in the service or the application layer, and doing all the work in a single transaction.
is it safe to share the hibernate entities across different layer
Yes. What is not safe is to use an entity instance across several threads, because entities are not thread-safe.
a database query is fired which i think is messing up with the "seperation of concerns" as database related operation should be constrained to the dao layer. am i right?
No. The service layer doesn't contain any code to trigger this database query. It happens transparently, without the service layer having to care about it, and because you chose to make the association lazy.
is making two seperate DTOs a good idea here and passing them across layers.
No. DTOs are useful to transfer data between separate applications. Inside your application, working with managed entities is the correct way.
i want to keep my service layer(not yet implemented) to be isolated from things specific to hibernate like sessions and database related operations(CRUD). how can i achieve it.
By using Spring or Java EE (or any other framework that has this feature) which allow using declarative transactions and deal with the task of opening/closing sessions and transactions for you whenever a transactional method is called.
You should also avoid using the proprietary Session API, and use the standard JPA API instead.
I was trying to use Spring Data JPA on Spring Boot and I kept getting error, I can't figure out what the problem is:
Unable to locate Attribute with the the given name [firstName] on
this ManagedType [com.example.h2demo.domain.Subscriber]
FirstName is declared in my entity class. I have used a service class with DAO before with different project and worked perfectly.
My Entity class (getters and setters are also in the class) :
#Entity
public class Subscriber {
#Id #GeneratedValue
private long id;
private String FirstName,LastName,Email;
public Subscriber(long id, String firstName, String lastName, String email) {
this.id = id;
this.FirstName = firstName;
this.LastName = lastName;
this.Email = email;
}
}
...
My Repository Class
#Component
public interface SubscriberRepository extends JpaRepository<Subscriber,Long> {
Subscriber findByFirstName(String FirstName);
Subscriber deleteAllByFirstName(String FirstName);
}
My Service Class
#Service
public class SubscriberService {
#Autowired
private SubscriberRepository subscriberRepository;
public Subscriber findByFirstName(String name){
return subscriberRepository.findByFirstName(name);
}
public Subscriber deleteAllByFirstName(String name){
return subscriberRepository.deleteAllByFirstName(name);
}
public void addSubscriber(Subscriber student) {
subscriberRepository.save(student);
}
}
And My Controller class:
#RestController
#RequestMapping("/subscribers")
public class SubscriberController {
#Autowired
private SubscriberService subscriberService;
#GetMapping(value = "/{name}")
public Subscriber findByFirstName(#PathVariable("name") String fname){
return subscriberService.findByFirstName(fname);
}
#PostMapping( value = "/add")
public String insertStudent(#RequestBody final Subscriber subscriber){
subscriberService.addSubscriber(subscriber);
return "Done";
}
}
Try changing private String FirstName,LastName,Email; to private String firstName,lastName,email;
It should work.
findByFirstName in SubscriberRepository tries to find a field firstName by convention which is not there.
Further reference on how properties inside the entities are traversed https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
The same problem was when i had deal with Spring Data Specifications (https://www.baeldung.com/rest-api-search-language-spring-data-specifications)
Initial piece of code was:
private Specification<Project> checkCriteriaByProjectNumberLike(projectNumber: String) {
(root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("project_number"), "%" + projectNumber)
}
The problem was in root.get("project_number"). Inside the method, I had to put the field name as in the model (projectNumber), but I sent the field name as in the database (project_number).
That is, the final correct decision was:
private Specification<Project> checkCriteriaByProjectNumberLike(projectNumber: String) {
(root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("projectNumber"), "%" + projectNumber)
}
After I change my entity class variables from capital letter to small letter for instance Username to username the method Users findByUsername(String username); is working for me now .
As per specification , the property names should start with small case.
...The resolution algorithm starts with interpreting the entire part (AddressZipCode) as the property and checks the domain class for a property with that name (uncapitalized)....
It will try to find a property with uncapitalized name. So use firstName instead of FristName and etc..
in my project I have a library module and an application module using it. In both modules I have the same gradle dependencies on Android Architecture Components library:
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.0.0"
implementation "android.arch.lifecycle:common-java8:1.0.0"
// Room
implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
In my library module I have defined a User entity
#Entity(tableName = "users",
indices = {#Index(value = {"firstName", "lastName"})})
public class User {
public enum ROLE {
...
}
public enum FEEDBACK_LEVEL {
...
}
#PrimaryKey
public int id;
#TypeConverters(UserConverters.class)
ROLE role;
#TypeConverters(UserConverters.class)
FEEDBACK_LEVEL feedbackLevel;
public String firstName;
public String lastName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public ROLE getRole() {
return role;
}
public void setRole(ROLE role) {
this.role = role;
}
public FEEDBACK_LEVEL getFeedbackLevel() {
return feedbackLevel;
}
public void setFeedbackLevel(FEEDBACK_LEVEL feedbackLevel) {
this.feedbackLevel = feedbackLevel;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
and the related DAO interface
#Dao
public interface UserDAO {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insertUser(User ... u);
#Query("select * from users where users.id = :userId")
LiveData<User> getUser(int userId);
}
In my application module I've created my database in which I'm using the entity defined in the library project
#Database(entities = {User.class}, version = 1)
public abstract class TDatabase extends RoomDatabase{
private static TDatabase sInstance;
public static TDatabase getInstance(final Context c) {
if(sInstance == null)
sInstance = Room.databaseBuilder(c, TDatabase.class, "t_db").build();
return sInstance;
}
public abstract UserDAO userDao();
}
The problem is that when I try to refer to a method parameter in a #Querystatement using its name I get the following error
Error:Each bind variable in the query must have a matching method parameter. Cannot find method parameters for :userId.
If I change the #Query from
#Query("select * from users where users.id = :userId")
LiveData<User> getUser(int userId);
to
#Query("select * from users where users.id = :arg0")
LiveData<User> getUser(int userId);
everything works fine.
Am I doing some mistakes? Why I'm getting this error?
I've googled for a solution but I found only results referring to Kotlin while I'm using Java.
This issue reported at https://issuetracker.google.com/issues/68118746 and fixed in version 1.1.0-alpha3, but only for Kotlin code since parameter names are always stored in Kotlin classes metadata.
For Java, there is only workaround with :arg0 until annotation like NamedArg will be added to Room.
I think you should use it like that:
#Query("select * from users where id = (:userId)")
LiveData<User> getUser(int userId);
This problem still pops up for me sometimes when working on db logic, but "Clean Project" usually fixes it in IntelliJ IDEA (should work just the same in Android Studio).
My professor gave a sample Spring MVC ORM project with Hibernate but I can not figure out the sequence of events involved, in particular about the usage of service business object.
This is just a little part of the project, just to make my ideas clearer.
domain:
#Entity
#Table(name = "department")
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long uid;
private String name;
#OneToMany(mappedBy="department",cascade=CascadeType.PERSIST)
private List<Employee> employees = new ArrayList<Employee>();
public Department() {
}
public Department(String name) {
this.name = name;
}
// getters, setters, hashcode() and equals(), toString()...
controller:
#Controller
#RequestMapping("/department")
public class DepartmentController {
#Autowired
#Qualifier("departmentBO")
private DepartmentBO departmentBO;
static final Logger logger = Logger.getLogger(DepartmentController.class);
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String departmentHome(Model model) {
logger.debug("department home() invoked");
List<Department> list = departmentBO.findAllDepartments();
model.addAttribute("list", list);
return "departments";
}
// i'll paste just the first controller ;)
business:
public interface DepartmentBO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department department);
public void update(Department department);
}
business/impl:
#Service
#Transactional
public class DepartmentBoImpl implements DepartmentBO {
#Autowired
private DepartmentDAO departmentDao;
static final Logger logger = Logger.getLogger(DepartmentBoImpl.class);
#Override
public void save(Department department) {
departmentDao.save(department);
}
#Override
public void update(Department department) {
departmentDao.update(department);
}
#Override
public void delete(long uid) {
departmentDao.delete(uid);
}
#Override
public List<Department> findAllDepartments() {
return departmentDao.findAllDepartments();
}
#Override
public Department findByUid(Long uid) throws DataAccessException {
return departmentDao.findByUid(uid);
}
}
dao:
public interface DepartmentDAO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department user);
public void update(Department user);
}
dao/impl:
#Repository
public class DepartmentDAOImplSf implements DepartmentDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void delete(long uid) {
Department department = (Department) sessionFactory.getCurrentSession()
.get(Department.class, uid);
sessionFactory.getCurrentSession().delete(department);
}
#Override
public void save(Department department) {
sessionFactory.getCurrentSession().save(department);
}
#Override
public void update(Department department) {
sessionFactory.getCurrentSession().saveOrUpdate(department);
}
#Override
public List<Department> findAllDepartments() {
List<Department> list = (List<Department>) sessionFactory
.getCurrentSession()
.createQuery("FROM Department").list();
return list;
}
#Override
public Department findByUid(Long uid) {
Department department = (Department) sessionFactory
.getCurrentSession().get(Department.class, uid);
return department;
}
}
I know that the order is: domain model -> controller-> service -> dao ->db, but why use a DepartmentBO? and why DepartmentBoImpl autowired DepartmentDao? Who of them act first? Something that i'm not understanding is messing up my conception of how it works and the sequence of the process..
Thanks for your help ;)
EDIT: "
In few words my question is, what is the sequence of this code? user goes on the /home page that redirect on "departments" page. But what happen before this --> "List list = departmentBO.findAllDepartments();" ?;)
When the departmentBO.findAllDepartments() method is called if you look at the code it invokes the sessionFactory. That is an internal factory class in Hibernate that basically builds a transactional connection to the DB in order to run a query. You are defining the query in the createQuery method and then ultimately executing it with the list() method. These two methods are part of the database session that Hibernate has instantiated.
Departments Page -> departmentBO.findAllDepartments() -> sessionFactory -> createQuery -> list()
Or in pseudo code-ish
Departments Page -> execute findAllDepartments method -> fetch / build a database connection -> define the query -> execute the query -> Return the list!