0.hibernate 6 Final
0.hibernate 6 Final
-----------------------
TOPICS:
======
1. Hello World
2. CRUD application
3. Primary key genearation strategy
4. More annoations
5. Relation mapping
Many-to-one mapping
one-to-one mapping
Many-to-Many mapping
Why hibernate?
-------------
->oo way of thinking
->lazy and eager loading
->cascading
->automatic dirty checking
->transactional write behind
->first level caching
@Table(name = "customer_table")
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String address;
private String mobile;
private String email;
private Date dob;
}
StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
@Entity(name="customer_entity")
@Table(name="customer_table")
public class Customer {
@Id
@Column(name="customer_Id")
private int customerId;
@Column(name="customer_Name")
private String customerName;
@Column(name="customer_Addess")
private String customerAddess;
@Temporal(TemporalType.DATE)
private Date customerDob;
@Transient
private String customerPassword;
@Enumerated(EnumType.STRING)
private CustomerType customerType;
Note @DynamicUpdate
-------------------
Note: We can apply annotation @DynamicUpdate annotation on pojo, so that
hibernate only
update field that need to, otherwise hibernate try to update all field except
pk
Hibernate fire update iff the state is dirty (dirty checking)
session.load()
It will always return a proxy (Hibernate term) without hitting the
database.
proxy object look like a temporary fake object.
If no row found , it will throws an ObjectNotFoundException.
session.get()
It always hit the database and return the real object,
an object that represent the database row, not proxy.
with @Id
-----------
Steps:
@Embeddable
public class CustomerKey implements Serializable{
private static final long serialVersionUID = -4336329019606358832L;
private int customerId;
private String customerRegistrationId;
with @IdClass
----------------
@Entity
@IdClass(EmployeeId.class)
public class Employee {
@Id
private String branchName;
@Id
private int idEmployee;
}
Transient
------------
=>not related to hibernate only in java space not in db space
=>Transient objects do not have association with the databases and session
objects
Customer c=new Customer();
c.setName("raja");
c.setAddress("Delhi");
Persistent
---------
Hibernate care about it
Detached
-----------
=> in java space and in db space
=> The detached object have corresponding entries in the database
session.close();
new()
|
Transient --> Persistent --> Detached
session.save() session.close();
get()
|
Persistent --> Detached
session.close();
|<-------------->|
session
// time gap
session = fac.openSession();
session.beginTransaction();
c.setAddress("noida");// here user in detached state
session.update(c);
session.getTransaction().commit();
@Entity
@Table(name="customer")
@SecondaryTable(name="customerDetails")
public class Customer {
@Id
private int customerId;
private String customerName;
@Column(table="customerDetails")
private int customerCreditScore;
@Column(table="customerDetails")
private int customerRewardPoints;
}
one to many
--------------
Consider:-
1 N
reverse owner owner of relationship
@Entity
public class Employee {
@Id
@GeneratedValue
private int empId;
private String empName;
@ManyToOne
private Department department;
@Entity
public class Department {
@Id
@GeneratedValue
private int deptId;
private String detpName;
@OneToMany(mappedBy="department")
private Collection<Employee>employees=new ArrayList<Employee>();
one-to-one mapping
----------------------
1 1
Employee<>----------Parking
@Entity
public class Parking {
@Id
@GeneratedValue
private int partingId;
private String parkingLocation;
@OneToOne(mappedBy = "parking")
private Employee employee;
@Entity
public class Employee {
@Id
@GeneratedValue
private int empId;
private String empName;
@OneToOne
private Parking parking;
}
@BatchSize(size=5) on emp
http://www.javamakeuse.com/2015/03/tutorial-hibernate-4-batch-fetching.html
Many-to-Many mapping
----------------------
N N
Employee----<>----- Project
Create POJO
------------
@ManyToMany
private Collection<Project> projects = new ArrayList<Project>();
}
@Entity
public class Project {
@Id
@GeneratedValue
private int projectId;
private String projectName;
@ManyToMany(mappedBy="projects")
private Collection<Employee> employees = new ArrayList<Employee>();
}
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String isbn;
private String title;
private String author;
private double price;
@ElementCollection(fetch=FetchType.LAZY)
@CollectionTable(name="book_reviews")
@Column(name="review")
private List<String> reviews=new ArrayList<String>();
Inheritance in Hibernate
----------------------------------
DB do not hv notion of Inhertance
Consider:
SavingAccount CurrentAccount
intrestRate overdraft
//
==> Here only one table is going to be created, all fields mapped to single
table.
==> Not very memory efficient, Faster, support polymorphic quaries
==> cant force not null constrants
@Entity
@Table(name = "Account")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="accountType",discriminatorType=DiscriminatorType.STRING)
@Entity
@Table(name="Account")
@DiscriminatorValue("C")
public class CurrentAccount extends Account {
private double overdraft;
@Entity
@Table(name="Account")
@DiscriminatorValue("S")
public class SavingAccount extends Account {
private double intrestRate;
@Entity
@Table(name = "Account")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Account{
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private int accountId;
private String accountHolderName;
private double balance;
@Entity
@Table(name="SavingAccount")
public class SavingAccount extends Account{
private double intrestRate;
@Entity
@Table(name="CurrentAccount")
public class CurrentAccount extends Account{
private double overdraft;
}
steps;
@Embeddable
public class Address {
private String city;
private String country;
@Embedded
private Addess address;
Saving Collections
-----------------------
Set<Address>addresses=new HashSet();
class User{
@ElementCollection
Set<Address>addresses=new HashSet();
@Embeddable
class Address{
Now save it
-----------------
user.getLisOfAddresses().add(address1);
user.getLisOfAddresses().add(address2);
Save User
two table created : one for user
another with the name : user_addresses hibernate decide for you.
Note:
If u want to hv a custom name
@JoinTable(name="User_address")
Set<Address>addresses=new HashSet();
_____________________________
then what?
Hibernate batch
----------------
=> by default, Hibernate will cache all the persisted objects in the session-
level cache and ultimately
your application would fall over with an OutOfMemoryException somewhere
around the 50,000th row.
=> You can resolve this problem if you are using batch processing with
Hibernate.
=> This will tell the hibernate container that every X rows to be inserted as
batch.
To implement this in your code we would need to do little modification as
follows:
while(studentCursor .next())
{
Student student = (Student) studentCursor.get(0);
student.setName("DEV");
seession.update(student);
if ( ++count % 50 == 0 ) {
session.flush();
session.clear();
}
}
tx.commit();
session.close();
hibernate queries
_________________
HQL Syntax
___________
class Customer{
private int id;
private String name;
private String address;
Parameter Binding
__________________
Ex:
query.setString(0, "noida");
Ex:
Customer c= new Customer ();
c.setName("rajesh");
query .setString("name","raja");
__________________________________
Named Quaries and native Quaries
__________________________________
==> Give unique name to the Queries that work for entire application.
==>The application can use the query by using the name of the query
Ex:
@NamedNativeQueries({
@NamedNativeQuery(
name = "findCustomer.byAddress", query = "select * from Customer c
where c.address = :address" , resultClass = Customer.class
)
})
@Entity
public class Customer {
@Id
@GeneratedValue
private int id;
Query query =
session.getNamedQuery("findCustomer.byId").setInteger("id", 3);
Delete:
_______
String HQL = "DELETE FROM Customer WHERE id=:id";
Query query = session.createQuery(HQL);
query.setParameter("id", 5);
session.beginTransaction();
int executeUpdate = query.executeUpdate();
session.getTransaction().commit();
if(executeUpdate>0)
System.out.println("custoemr is deleted..");
Update:
_______
session.beginTransaction();
int executeUpdate = query.executeUpdate();
session.getTransaction().commit();
if(executeUpdate>0)
System.out.println("customer email is updated..")
Insert:
________
String HQL = "INSERT INTO
Employee(employeeName,doj,salary,bonus,email,designation)"+
"SELECT employeeName,doj,salary,bonus,email,designation FROM
BackupEmployee";
_________________________
Criteria API in Hibernate
___________________________
criteria.add(Restrictions.eq("name", "amit"));
criteria.add(Restrictions.le("id", 5));
Note:
------
Restrictions.ge
Restrictions.le
Restrictions.ne
Restrictions.in
------------------------
Criteria criteria = session.createCriteria(Customer.class);
Restrictions.like
------------------
Restrictions.isNull
_________________
criteria.add(Restrictions.isNull("address"));
Restrictions.isNotNull
Restriction.between
_________________
criteria.add(Restrictions.between("id", 3, 7));
Restriction.allEq
_________________
________________
JPQL examples:
______________
@Table(name = "person_table")
@Entity(name="people")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
@Temporal(TemporalType.DATE)
private Date birthDate;
}
Main:
______
EntityManagerFactory factory =
Persistence.createEntityManagerFactory("demo");
EntityManager em = factory.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Person p = new Person("raj", "gupta", "[email protected]", new Date());
em.persist(p);
em.createQuery("from people");
em.createNativeQuery("select * from person_table");
transaction.commit();
em.close();
______
joins
_______
@Entity
@NamedQueries({
@NamedQuery(name="Person.everyone", query = "from Person")
})
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
@ManyToOne(cascade = CascadeType.PERSIST)
private Address address;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id")
private List<PhoneNumber> numbers = new ArrayList<>();
@Entity
public class PhoneNumber {
@Id
@GeneratedValue
private Long id;
private String number;
private String type;
@Entity
public class Address {
@Id
@GeneratedValue
private Long id;
private String street;
private String city;
private String state;
private String zip;
Quaries examples:
_________________
polymorphicQuery
_________________
aliasesQuery
____________
pagination
______________
orderBy
_________
whereClause
___________
queryParameters
_____________
//NOT Good
TypedQuery<Person> query =
em.createQuery("from Person p where p.firstName =
'"+firstName+"'", Person.class);
1. Named Parameters
_________________
2. position
_______________
TypedQuery<Person> query =
em.createQuery("from Person p where p.lastName = ?1 and p.firstName =
?0", Person.class);
query.setParameter(0, "raj");
query.setParameter(1, "gupta");
singleResult
_________________
specialAttributeId
_________________
Consider:
-------
public class Person {
@Id
@GeneratedValue
private Long personId;
}
List<Person> p = query.getResultList();
__________
join
___________
1. implicit join
_________________
2. explicit join
TypedQuery<Person> query =
em.createQuery("select p from Person p join p.address addr where
addr.state = 'delhi'", Person.class);
List<Person> p = query.getResultList();
Join 1 to many:
_________________
1 1
Person--------<>--------Phone
TypedQuery<Object[]> query =
em.createQuery("from Person p join p.numbers n where n.number like
'641%'", Object[].class);
List<Object[]> list = query.getResultList();
for(Object[] obj : list){
System.out.println((Person)obj[0]);
System.out.println((PhoneNumber)obj[1]);
}
TypedQuery<Person> query2 =
em.createQuery("select p from Person p join p.numbers n where n.number like
'641%'", Person.class);
List<Person> personList = query2.getResultList();
use DISTINCT keyword
_________________
TypedQuery<Person> query2 =
em.createQuery("select distinct p from Person p join p.numbers n where
n.number like '641%'", Person.class);
List<Person> personList = query2.getResultList();
System.out.println(personList);
joinFetch
__________
TypedQuery<Person> query2 =
em.createQuery("from Person p join fetch p.numbers n where n.number
like '641%'", Person.class);
List<Person> personList = query2.getResultList();
hibernate performace:
_______________________
hibernate Optimization:
_______________________
N+1 problem
Dynamic solution:
__________________
static solution:
_________________
@LazyCollection(LazyCollection.EXTRA)
class Dept{
@OneToMany
@JoinColumn
@LazyCollection(LazyCollection.EXTRA)
List<Emp> emp=new AL<>();
dept
dept.getEmps().size()
consider example:
__________________
1 1
customer ------------------ Address
|
| N
------------------------- Book
|
| N
------------------------ Movie
|
| 1
N ------------------------- SalesRep
@Entity
public class Customer {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
@OneToOne(cascade = CascadeType.ALL)
private Address address;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private List<Movie> movies = new ArrayList<>();
@ManyToOne(cascade = CascadeType.ALL)
private SalesRep salesRep;
}
@Entity
public class Address {
@Id
@GeneratedValue
private Long id;
private String city;
private String state;
}
@Entity
public class Author {
@Id
@GeneratedValue
private Long id;
private String name;
@Entity
public class Book {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
private Author author;
}
@Entity
public class Movie {
@Id
@GeneratedValue
private Long id;
private String name;
this.name = name;
}
@Entity
public class SalesRep {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
private Address address;
}
lazy or Eager
___________
class A{
cartesianProduct_BAD
______________________
nPlusOneProblem
________________
entityGraphAndJoinFetch
________________________
2. Join Fecth
_________________
TypedQuery<Customer> query =
em.createQuery("from Customer c join fetch c.address join fetch c.books b
join fetch b.author", Customer.class);
___________________________
Hibernate caching example:
____________________________
http://howtodoinjava.com/2013/07/04/hibernate-ehcache-configuration-tutorial/
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- disable the second level cache * -->
<property
name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegi
onFactory</property>
<property
name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property
name="hibernate.cache.region.provider_class">net.sf.ehcache.hibernate.EhCacheProvid
er</property>
<property name="hbm2ddl.auto">update</property>
<!-- jdbc connection pool build in -->
<property name="connection.pool_size">1</property>
<!-- <property name="current_session_context_class">thread</property>
-->
</session-factory>
</hibernate-configuration>
@Entity
@Table(name="customer_table2")
@Cacheable
//@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
SessionFactory factory=null;
try{
factory=new AnnotationConfiguration()
.configure("hibernate2.cfg.xml").buildSessionFactory();
Session session=factory.openSession();
session.getTransaction().begin();
session.getTransaction().commit();
session.close();
Session session2=factory.openSession();
session2.getTransaction().begin();
session2.getTransaction().commit();
session2.close();
}finally{
if(factory!=null)
factory.close();
}
//Query cache
Query query=session.createQuery("from Customer where id=121");
query.setCacheable(true);
mapping
one to many
one to one: unidirectional bidirectional
try ex to understand N+1
many to many, use @joinTable and @joinColumn annotation
inheritance:
single table per class her
jointed
table per class
Domain design
______________
N M 1 N
- Book --------<>------- Author ----<>-------Address
|
----- List of phones
|
------List of emails
1 N
- Book --------<>------- Review
- Book
|
-----
| |
Ebook PaperBook
___________________________________________________________________________________
____________________________________
parking1.setEmployee(employee1);
parking2.setEmployee(employee2);
parking3.setEmployee(employee3);
parking4.setEmployee(employee4);
parking5.setEmployee(employee5);
Session session=factory.openSession();
session.getTransaction().begin();
session.persist(parking1);
session.persist(parking2);
session.persist(parking3);
session.persist(parking4);
session.persist(parking5);
//
// session.persist(employee1);
// session.persist(employee2);
// session.persist(employee3);
// session.persist(employee4);
// session.persist(employee5);
//
parking1.setEmployee(employee1);
parking2.setEmployee(employee2);
parking3.setEmployee(employee3);
parking4.setEmployee(employee4);
parking5.setEmployee(employee5);
employee1.setParking(parking1);
employee2.setParking(parking2);
employee3.setParking(parking3);
employee4.setParking(parking4);
employee5.setParking(parking5);
session.persist(parking1);
session.persist(parking2);
session.persist(parking3);
session.persist(parking4);
session.persist(parking5);
department1.getEmployees().add(employee1);
department1.getEmployees().add(employee2);
department2.getEmployees().add(employee3);
department2.getEmployees().add(employee4);
department3.getEmployees().add(employee5);
department3.getEmployees().add(employee6);
department3.getEmployees().add(employee7);
employee1.setDepartment(department1);
employee2.setDepartment(department1);
employee3.setDepartment(department2);
employee4.setDepartment(department2);
employee5.setDepartment(department3);
employee6.setDepartment(department3);
employee7.setDepartment(department3);
session.save(department1);
session.save(department2);
session.save(department3);
session.save(employee1);
session.save(employee2);
session.save(employee3);
session.save(employee4);
session.save(employee5);
session.save(employee6);
session.save(employee7);
References:
----------
http://learningviacode.blogspot.in/2012/02/hibernate-object-life-cycle.html
https://www.objectdb.com/
@Formula
__________
@Entity
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Column
private LocalDate dateOfBirth;
@Formula(value = "date_part('year', age(dateOfBirth))")
private int age;
@PrePersist
___________
@Entity
public class Author {
...
@PrePersist
private void initializeCreatedAt() {
this.createdAt = LocalDateTime.now();
log.info("Set createdAt to "+this.createdAt);
}
}
hib lob:
------
https://www.baeldung.com/hibernate-lob
hib life cycle:
------------
http://learningviacode.blogspot.com/2012/02/hibernate-object-life-cycle.html
<Resource
name="jdbc/test"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/exp121"
username="root"
password="root" >
</Resource>
@Resource(name="jdbc/test")
private DataSource ds;
private Connection conn;
conn = ds.getConnection();
dependencies:
--------------
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<hibernate.version>6.1.5.Final</hibernate.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mysql.version>8.0.31</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- JAXB Implementation -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>3.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>