ORM.
Hibernate
Framework
Part 2
IT Academy
Agenda
Session Factory
Configuration
Entity life cycle
HQL
Named and Native Query
LazyInitializationException
Session Factory
It's an interface implemented using the singleton pattern.
It's created using the configuration provided by the configuration file.
It's thread-safe, so it's created once during the application's lifetime, and
multiple users or threads can access it at the same time without any
concurrency issue.
As a SessionFactory object is immutable, changes made to the configuration will
not affect the existing factory object.
It's a factory class, and its main duty is to create, manage, and retrieve a session
on request. A Session is used to get a physical connectivity with the database.
Configuration. XML resource
s
hibernate.cfg.xml
…
<hibernate-configuration>
<session-factory>
<!-- JDBC Database connection settings -->
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate_db?useSSL=false</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create-drop</property>
<mapping class="entity.Student" />
</session-factory>
</hibernate-configuration>
Properties & programmatic
configurations
hibernate.properties
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/testdb
hibernate.connection.username=root
Configuration cfg = new Configuration()
hibernate.connection.password=root
.addClass(org.hibernate.auction.Item.class)
show_sql=true .addClass(org.hibernate.auction.Bid.class)
.setProperty("hibernate.dialect",
hbm2ddl.auto=update
"org.hibernate.dialect.H2Dialect") .setProperty("hibernate.connection.datasource",
… "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true");
resource
s
Descriprion of properties
hibernate.dialect This property makes Hibernate generate the appropriate SQL for the chosen
database.
hibernate.connection.driver_cla The JDBC driver class.
ss
hibernate.connection.url The JDBC URL to the database instance.
hibernate.connection.username The database username.
hibernate.connection.password The database password.
hibernate.connection.pool_size Limits the number of connections waiting in the Hibernate database
connection pool.
hibernate.connection.autocomm Allows autocommit mode to be used for the JDBC connection.
it validate | update | create | create-drop
hibernate.hbm2ddl.auto Automatically validates or exports schema DDL to the database when
the SessionFactory is created. With create-drop, the database schema will be
dropped when the SessionFactory is closed explicitlly
hibernate.show_sql Write all SQL statements to console. This is an alternative to setting the log
category org.hibernate.SQL to debug.
Create SessionFactory
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure( "org/hibernate/example/hibernate.cfg.xml" )
.build();
Metadata metadata = new MetadataSources( standardRegistry )
.addAnnotatedClass( MyEntity.class )
.addAnnotatedClassName( "org.hibernate.example.Customer" )
.addResource( "org/hibernate/example/Order.hbm.xml" )
.addResource( "org/hibernate/example/Product.orm.xml" )
.getMetadataBuilder()
.build();
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
.applyBeanManager( getBeanManager() )
.build();
Create SessionFactory
public class HibernateSessionFactory {
private static StandardServiceRegistry registry;
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
registry = new StandardServiceRegistryBuilder().configure().build();
MetadataSources sources = new MetadataSources(registry);
Metadata metadata = sources.getMetadataBuilder().build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Exception e) {
e.printStackTrace();
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry); } } }
return sessionFactory;
}
public static void shutdown() {
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry); } }}
Entity LifeCycle
Employee emp = new
- Transient Employee();
emp.setName(”Ivan");
States
Session s =
- Persistent sessionFactory.openSession();
s.saveOrUpdate(emp);
emp.setName("Peter");
s.getTransaction().commit();
- Detached s.evict(emp); // or s.close();
emp.setName("Mary");
Employee mergedEmp =
s.merge(emp);
s.delete(emp);
- Removed s.close();
Hibernate LifeCycle
HQL JPQL
Query query = session.createQuery("update ContactEntity set firstName
= :nameParam, lastName = :lastNameParam, birthDate = :birthDateParam where
firstName = :nameCode");
query.setParameter("nameCode", "Nick");
query.setParameter("nameParam", "NickChangedName1");
query.setParameter("lastNameParam", "LastNameChanged1" );
query.setParameter("birthDateParam", new Date());
int result = query.executeUpdate();
Named Query
@org.hibernate.annotations.NamedQueries({
@org.hibernate.annotations.NamedQuery(name = "DeptEmployee_FindByEmployeeNumber",
query = "from DeptEmployee where employeeNumber = :employeeNo"),
@org.hibernate.annotations.NamedQuery(name = "DeptEmployee_UpdateEmployeeDepartment",
query = "Update DeptEmployee set department = :newDepartment where employeeNumber = :employeeNo"),
@org.hibernate.annotations.NamedQuery( name = "DeptEmployee_FindAllByDepartment",
query = "from DeptEmployee where department = :department", timeout = 1, fetchSize = 5)
})
Query<DeptEmployee> query = session.createNamedQuery("DeptEmployee_FindByEmployeeNumber", DeptEmployee.class);
query.setParameter("employeeNo", "001");
DeptEmployee result = query.getSingleResult();
Named Native Query
@org.hibernate.annotations.NamedNativeQueries(
@org.hibernate.annotations.NamedNativeQuery(name = "DeptEmployee_GetEmployeeByName",
query = "select * from deptemployee emp where name=:name",
resultClass = DeptEmployee.class)
)
Query<DeptEmployee> query = session.createNamedQuery("DeptEmployee_FindByEmployeeName", DeptEmployee.class);
query.setParameter("name", "John");
OR
List<DeptEmployee> result = query.list();
NativeQuery query = session.getNamedNativeQuery("DeptEmployee_FindByEmployeeName");
query.setParameter("name", "John ");
List<DeptEmployee> result = query.list();
CiteriaQuery
CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
Root<Person> personRoot = criteria.from( Person.class );
criteria.select(personRoot.get(“age”));
criteria.where( builder.equal( personRoot.get(“eyeColor”), "brown" ) );
List<Integer> ages = session.createQuery( criteria ).getResultList();
to-one –
Lazy and Eager fetching FetchType.EAGER
to-many –
FetchType.LAZY
EntityManager em = emf.createEntityManager(); @Entity
public class Author {
em.getTransaction().begin(); @Id @GeneratedValue
private Integer id;
TypedQuery<Author> q = private String name;
@OneToMany(mappedBy = "author")
em.createQuery("SELECT a FROM Author a", Author.class); private List<Book> books = new ArrayList<>();
//other code
List<Author> authors = q.getResultList(); }
@Entity
em.getTransaction().commit();
public class Book {
@Id @GeneratedValue
em.close(); private Integer id;
private String name;
for (Author author : authors) { @ManyToOne
@JoinColumn(name="AUTHOR_ID")
List<Book> books = author.getBooks(); private Author author;
//other code
log.info("... the next line will throw LazyInitializationException ..."); }
books.size();
}
Join Fetch
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
TypedQuery<Author> q = em.createQuery("SELECT a FROM Author a LEFT JOIN FETCH a.books", Author.class);
List<Author> authors = q.getResultList();
em.getTransaction().commit();
em.close();
for (Author a : authors) {
log.info(a.getName() + " wrote the books "
+ a.getBooks().stream().map(b -> b.getTitle()).collect(Collectors.joining(", "))
);
}
DTO projection
@Entity
EntityManager em = emf.createEntityManager(); public class Author {
em.getTransaction().begin(); @Id @GeneratedValue
private Integer id;
private String name;
TypedQuery<AuthorDto> q = em.createQuery( @OneToMany(mappedBy = "author")
"SELECT new AuthorDto(a.id, a.name,b.titles) private List<Book> books = new ArrayList<>();
//other code
FROM Author a JOIN a.books b", AuthorDto.class); }
List<AuthorDto> authors = q.getResultList();
public class AuthorDto {
em.getTransaction().commit();
private final Integer id;
em.close(); private final String name;
private final List<String> titles;
for (AuthorDto author : authors) {
// other code
log.info(author.getName() + " wrote the book " + author.getTitles()); }
}
Spring Data JPA
public interface CrudRepository<T, ID extends Serializable> extends
Repository<T, ID>
T save(T entity);
Iterable<T> saveAll(Iterable<T> entities)
Optional<T> findById(ID primaryKey);
boolean existsById(ID primaryKey);
void delete(T entity);
long count();
…
Spring Data JPA. Implementation
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-
methods.details
@Entity
public class Employee { 1 @Repository
public interface CustomizedEmployeesCrudRepository extends 2
CrudRepository<Employees, Long> {
@Id Optional<Employees> findByFirstNameAndLastName(String firstName, String lastName);
@GeneratedValue(strategy =
List<Employees> findFirst5ByFirstNameStartsWithOrderByFirstName(String
GenerationType.IDENTITY)
firstNameStartsWith);}
private Long id;
private String firstName; @Service
private String lastName; public class EmployeesDataService { 3
private String email; @Autowired
…} private CustomizedEmployeesCrudRepository
employeesCrudRepository;
@Transactional public void testEmployeesCrudRepository() {
Optional<Employees> employeesOptional =
employeesCrudRepository.findById(127L); …. }
Spring Data JPA. Query
public interface AuthorRepository extends JpaRepository<Author, Long> {
@Query("FROM Author WHERE firstName = ?1 OR lastName = ?1 ")
List<Author> findByName(String name);
@Query("SELECT a FROM Author a WHERE firstName = :firstName AND lastName = :lastName")
List<Author> findByFirstNameAndLastName(@Param("lastName") String firstName, @Param("firstName") String lastName);
@Query("UPDATE Author SET firstName = :prefix || firstName")
@Modifying
void addPrefixToFirstName(@Param("prefix") String prefix);
}
Service layer
• The DAO layer's main goal is to handle the details of the persistence mechanism.
• While the service layer stands on top of it to handle business requirements.
@Service – component in service
layer
• Provides separation of concern
• Provides Security
• Provide Loose Coupling
SoftServe Confidential