๐ Hibernate ORM: ๊ฐ์ฒด-๊ด๊ณ ๋งคํ์ ํ์ค ๐

์๋ , ์น๊ตฌ๋ค! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฐพ์์์ด. ๋ฐ๋ก Hibernate ORM์ ๋ํด ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ์ผ. ์๋ฐ ๊ฐ๋ฐ์๋ผ๋ฉด ํ ๋ฒ์ฏค์ ๋ค์ด๋ดค์ ์ด ๊ฐ๋ ฅํ ๋๊ตฌ, ์ด๋ค ๋งค๋ ฅ์ด ์๋์ง ํจ๊ป ์์๋ณด์๊ณ ! ๐
์ฐ๋ฆฌ๊ฐ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ค ๋ณด๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์จ๋ฆํ๋ ๊ฒฝ์ฐ๊ฐ ์ ๋ง ๋ง์ง? ๊ทธ๋ด ๋๋ง๋ค SQL ์ฟผ๋ฆฌ๋ฅผ ์ผ์ผ์ด ์์ฑํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๋ณํํ๋ ์์ ... ์์งํ ์ข ๊ท์ฐฎ์ง ์์? ๐ฅฑ ๋ฐ๋ก ์ด๋ฐ ๊ณ ๋ฏผ์ ํด๊ฒฐํด์ฃผ๋ ๊ฒ Hibernate ORM์ด์ผ!
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Hibernate์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ๊น? ์ค๋น๋์ด? ๊ทธ๋ผ ์ถ๋ฐ! ๐๐จ
๐ Hibernate๋ ๋ฌด์์ธ๊ฐ? ๐
Hibernate๋ ์๋ฐ ์ง์์์ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ORM ํ๋ ์์ํฌ์ผ. 2001๋ ์ ์ฒ์ ๋ฑ์ฅํ๋๋ฐ, ๊ทธ ์ดํ๋ก ๊ณ์ํด์ ๋ฐ์ ํ๋ฉด์ ์๋ฐ ๊ฐ๋ฐ์๋ค์ ์ฌ๋์ ๋ฌ๋ฟ ๋ฐ๊ณ ์์ง. ๐ฅฐ
Hibernate์ ํต์ฌ ๋ชฉํ๋ ๊ฐ๋ฐ์๊ฐ ๋ ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ฃผ๋ ๊ฑฐ์ผ. SQL์ ์ง์ ์์ฑํ๋ ๋์ , ์๋ฐ ๊ฐ์ฒด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํตํ ์ ์๊ฒ ํด์ค๋ค๊ณ ๋ณด๋ฉด ๋ผ.
Hibernate๋ฅผ ์ฌ์ฉํ๋ฉด ์ป์ ์ ์๋ ์ฅ์ ๋ค์ด ์ ๋ง ๋ง์. ๋ช ๊ฐ์ง๋ง ์ดํด๋ณผ๊น?
- โ ์์ฐ์ฑ ํฅ์: SQL ์ฟผ๋ฆฌ๋ฅผ ์ผ์ผ์ด ์์ฑํ ํ์๊ฐ ์์ด์ ธ์ ๊ฐ๋ฐ ์๊ฐ์ด ๋จ์ถ๋ผ.
- โ ์ ์ง๋ณด์์ฑ ์ฆ๊ฐ: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๊ฐ ๋ณ๊ฒฝ๋์ด๋ ์๋ฐ ์ฝ๋๋ฅผ ํฌ๊ฒ ์์ ํ ํ์๊ฐ ์์ด.
- โ ์ฑ๋ฅ ์ต์ ํ: Hibernate๊ฐ ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์ต์ ํํด์ฃผ๋๊น ์ฑ๋ฅ ๊ฑฑ์ ๋ ๋ ์ ์์ง.
- โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฆฝ์ฑ: ๋ค๋ฅธ ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ์ฝ๊ฒ ์ ํํ ์ ์์ด.
์ด๋ ๊ฒ ๋ณด๋๊น Hibernate ์ข ๋ฉ์ง ๋ ์ ๊ฐ์ง ์์? ๐ ๊ทผ๋ฐ ์ด๊ฒ ๋ค๊ฐ ์๋์ผ. Hibernate์ ์ง์ง ๋งค๋ ฅ์ ์ฌ์ฉํด๋ณด๋ฉด์ ๋ ๊น์ด ๋๋ ์ ์์ ๊ฑฐ์ผ. ์, ๊ทธ๋ผ ์ด์ Hibernate์ ํต์ฌ ๊ฐ๋ ๋ค์ ํ๋์ฉ ์ดํด๋ณผ๊น?
๐ Hibernate์ ํต์ฌ ๊ฐ๋ ๐
Hibernate๋ฅผ ์ ๋๋ก ์ดํดํ๋ ค๋ฉด ๋ช ๊ฐ์ง ํต์ฌ ๊ฐ๋ ์ ์์์ผ ํด. ํ๋์ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ์ดํด๋ณด์!
1. ์ํฐํฐ (Entity) ๐ค
์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ ์๋ฐ ํด๋์ค์ผ. ์๋ฅผ ๋ค์ด, 'User' ํ ์ด๋ธ์ด ์๋ค๋ฉด ๊ทธ์ ๋์ํ๋ 'User' ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฑฐ์ง. ์ด ํด๋์ค์ ์ธ์คํด์ค๋ ํ ์ด๋ธ์ ํ ํ(row)์ ๋ํ๋ด๊ฒ ๋ผ.
์ํฐํฐ ํด๋์ค๋ ๋ณดํต ์ด๋ ๊ฒ ์๊ฒผ์ด:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
@Column(name = "email")
private String email;
// ์์ฑ์, getter, setter ๋ฑ
}
์ฌ๊ธฐ์ @Entity, @Table, @Id, @Column ๊ฐ์ ์ ๋ ธํ ์ด์ ๋ค์ด ๋ณด์ด์ง? ์ด๊ฒ๋ค์ด Hibernate์๊ฒ "์ด ํด๋์ค๋ ํ ์ด๋ธ์ด๋ ๋งคํ๋๋ ๊ฑฐ์ผ!"๋ผ๊ณ ์๋ ค์ฃผ๋ ์ญํ ์ ํด.
2. ์ธ์ (Session) ๐
Hibernate ์ธ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฐ๊ฒฐ์ ๋ํ๋ด. ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์กฐํํ ๋ ์ด ์ธ์ ์ ํตํด ์์ ํ๊ฒ ๋ผ. ์ธ์ ์ ์ผ์ข ์ ์์ ๋จ์๋ผ๊ณ ๋ณผ ์ ์์ด.
์ธ์ ์ฌ์ฉ ์์:
Session session = sessionFactory.openSession();
try {
session.beginTransaction();
User user = new User("johndoe", "john@example.com");
session.save(user);
session.getTransaction().commit();
} finally {
session.close();
}
์ด๋ ๊ฒ ์ธ์ ์ ์ด๊ณ , ํธ๋์ญ์ ์ ์์ํ๊ณ , ์์ ์ ์ํํ ๋ค์, ํธ๋์ญ์ ์ ์ปค๋ฐํ๊ณ , ๋ง์ง๋ง์ผ๋ก ์ธ์ ์ ๋ซ๋ ๊ฒ ๊ธฐ๋ณธ์ ์ธ ํ๋ฆ์ด์ผ.
3. ์์์ฑ ์ปจํ ์คํธ (Persistence Context) ๐
์์์ฑ ์ปจํ ์คํธ๋ ์ํฐํฐ๋ฅผ ๋ณด๊ดํ๋ ๊ฐ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ์ ๊ฑฐ์ผ. ์ธ์ ์ ํตํด ์ํฐํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์กฐํํ๋ฉด, ์ด ์์์ฑ ์ปจํ ์คํธ๋ฅผ ๊ฑฐ์น๊ฒ ๋ผ.
์์์ฑ ์ปจํ ์คํธ์ ์ฃผ์ ํน์ง:
- ๐น 1์ฐจ ์บ์: ๋์ผํ ์ํฐํฐ๋ฅผ ๋ฐ๋ณตํด์ ์กฐํํ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ ธ์ ์ฑ๋ฅ์ ํฅ์์์ผ.
- ๐น ๋์ผ์ฑ ๋ณด์ฅ: ๊ฐ์ ์ํฐํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ์กฐํํด๋ ํญ์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํด.
- ๐น ํธ๋์ญ์ ์ ์ง์ํ๋ ์ฐ๊ธฐ ์ง์ฐ: INSERT ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๋ก ์คํํ์ง ์๊ณ ๋ชจ์๋๋ค๊ฐ ํ ๋ฒ์ ์คํํด ์ฑ๋ฅ์ ์ต์ ํํด.
- ๐น ๋ณ๊ฒฝ ๊ฐ์ง(Dirty Checking): ์ํฐํฐ์ ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ๊ฐ์งํด์ UPDATE ์ฟผ๋ฆฌ๋ฅผ ์คํํด.
4. HQL (Hibernate Query Language) ๐
HQL์ Hibernate๋ง์ ํน๋ณํ ์ฟผ๋ฆฌ ์ธ์ด์ผ. SQL๊ณผ ๋น์ทํ์ง๋ง, ํ ์ด๋ธ๊ณผ ์ปฌ๋ผ ๋์ ์ํฐํฐ์ ์์ฑ์ ์ฌ์ฉํด.
HQL ์์:
String hql = "FROM User u WHERE u.username = :username";
Query query = session.createQuery(hql);
query.setParameter("username", "johndoe");
List results = query.list();
์ด๋ ๊ฒ HQL์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ข ๋ฅ์ ์๊ด์์ด ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์์ด. Hibernate๊ฐ ์์์ ์ ์ ํ SQL๋ก ๋ณํํด์ฃผ๋๊น!
5. ๋งคํ (Mapping) ๐บ๏ธ
๋งคํ์ ์๋ฐ ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ฐ๊ฒฐํด์ฃผ๋ ๊ณผ์ ์ด์ผ. Hibernate์์๋ XML ํ์ผ์ด๋ ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ ์ด ๋งคํ์ ์ ์ํ ์ ์์ด.
์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ ๋งคํ ์์:
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "product_name")
private String name;
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
// ์์ฑ์, getter, setter ๋ฑ
}
์ฌ๊ธฐ์ @ManyToOne ๊ฐ์ ์ ๋ ธํ ์ด์ ์ ์ํฐํฐ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ ์ํด. ์ด ๊ฒฝ์ฐ, ์ฌ๋ฌ ์ ํ์ด ํ๋์ ์นดํ ๊ณ ๋ฆฌ์ ์ํ ์ ์๋ค๋ ์๋ฏธ์ผ.
์ด๋ ๊ฒ Hibernate์ ํต์ฌ ๊ฐ๋ ๋ค์ ์ดํด๋ดค์ด. ์ด๋, ์๊ฐ๋ณด๋ค ์ฌ๋ฏธ์์ง? ๐ค ์ด์ ์ด ๊ฐ๋ ๋ค์ ๋ฐํ์ผ๋ก Hibernate๋ฅผ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ๋ ์์ธํ ์์๋ณผ๊น?
๐ ๏ธ Hibernate ์ฌ์ฉํ๊ธฐ ๐ ๏ธ
์, ์ด์ Hibernate๋ฅผ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์์๋ณผ ์ฐจ๋ก์ผ. ์ค๋น๋์ด? ๊ทธ๋ผ ์์ํด๋ณผ๊น! ๐
1. Hibernate ์ค์ ํ๊ธฐ โ๏ธ
Hibernate๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ ํ๋ก์ ํธ์ Hibernate ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํด์ผ ํด. Maven์ ์ฌ์ฉํ๋ค๋ฉด pom.xml ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ ์์กด์ฑ์ ์ถ๊ฐํ๋ฉด ๋ผ:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.5.7.Final</version>
</dependency>
๊ทธ ๋ค์์ผ๋ก๋ Hibernate ์ค์ ํ์ผ์ ๋ง๋ค์ด์ผ ํด. ์ด ํ์ผ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ ๋ณด์ ๊ธฐํ Hibernate ๊ด๋ จ ์ค์ ๋ค์ด ๋ค์ด๊ฐ.
hibernate.cfg.xml ํ์ผ ์์:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>
2. ์ํฐํฐ ํด๋์ค ๋ง๋ค๊ธฐ ๐ฅ
์ด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํ๋ ์๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค ์ฐจ๋ก์ผ. ์์ ๋ดค๋ User ํด๋์ค๋ฅผ ์กฐ๊ธ ๋ ์์ธํ ์ดํด๋ณผ๊น?
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
// ์์ฑ์
public User() {}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
// Getter์ Setter ๋ฉ์๋
// ...
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
'}';
}
}
์ฌ๊ธฐ์ @Entity, @Table, @Id, @GeneratedValue, @Column ๊ฐ์ ์ ๋ ธํ ์ด์ ๋ค์ด Hibernate์๊ฒ ์ด ํด๋์ค๊ฐ ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋งคํ๋๋์ง ์๋ ค์ฃผ๊ณ ์์ด.
3. SessionFactory ๋ง๋ค๊ธฐ ๐ญ
SessionFactory๋ Session ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ณต์ฅ์ด์ผ. ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ณดํต ํ๋์ SessionFactory๋ง ๋ง๋ค์ด ์ฌ์ฉํด.
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
return new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
์ด๋ ๊ฒ ๋ง๋ SessionFactory๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ์ฌ์ฌ์ฉํ ์ ์์ด. ์ธ์ ์ด ํ์ํ ๋๋ง๋ค ์ด SessionFactory๋ฅผ ํตํด ์๋ก์ด ์ธ์ ์ ์ด๋ฉด ๋ผ!
4. CRUD ์ฐ์ฐ ์ํํ๊ธฐ โ๏ธ
์ด์ ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฑ(Create), ์ฝ๊ธฐ(Read), ๊ฐฑ์ (Update), ์ญ์ (Delete)ํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
Create (์์ฑ)
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
User user = new User("johndoe", "john@example.com", "password123");
session.save(user);
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
Read (์ฝ๊ธฐ)
Session session = HibernateUtil.getSessionFactory().openSession();
try {
User user = session.get(User.class, 1L); // 1L์ ์กฐํํ ์ฌ์ฉ์์ ID
System.out.println(user);
} finally {
session.close();
}
Update (๊ฐฑ์ )
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
User user = session.get(User.class, 1L);
user.setEmail("newemail@example.com");
session.update(user);
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
Delete (์ญ์ )
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
User user = session.get(User.class, 1L);
session.delete(user);
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
์ด๋, Hibernate๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ํ๋ ๊ฒ ์๊ฐ๋ณด๋ค ๊ฐ๋จํ์ง? ๐ ํ์ง๋ง ์ด๊ฒ ๋ค๊ฐ ์๋์ผ. Hibernate๋ ๋ ๋ณต์กํ ์ฟผ๋ฆฌ๋ ๊ด๊ณ ๋งคํ๋ ์ฒ๋ฆฌํ ์ ์์ด. ๋ค์ ์น์ ์์ ๋ ์์ธํ ์์๋ณด์!
๐ Hibernate ๊ณ ๊ธ ๊ธฐ๋ฅ ํํ ๐
์, ์ด์ Hibernate์ ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ณผ ์ฐจ๋ก์ผ. ์ค๋น๋์ด? ์ฐ๋ฆฌ์ Hibernate ์ฌํ์ ์ด์ ๋ถํฐ ์์์ด์ผ! ๐
1. ๊ด๊ณ ๋งคํ ๐
์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์๋ ํ ์ด๋ธ ๊ฐ์ ๊ด๊ณ๊ฐ ์ค์ํด. Hibernate๋ ์ด๋ฐ ๊ด๊ณ๋ฅผ ์ฝ๊ฒ ํํํ ์ ์๊ฒ ํด์ค.
์ผ๋๋ค(One-to-Many) ๊ด๊ณ
์๋ฅผ ๋ค์ด, ํ ๋ช ์ ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๊ฐ์ ๊ฒ์๊ธ์ ์์ฑํ ์ ์๋ค๊ณ ์๊ฐํด๋ณด์.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
private List<Post> posts = new ArrayList<>();
// ์์ฑ์, getter, setter ๋ฑ
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@ManyToOne
@JoinColumn(name = "author_id")
private User author;
// ์์ฑ์, getter, setter ๋ฑ
}
์ฌ๊ธฐ์ @OneToMany์ @ManyToOne ์ ๋ ธํ ์ด์ ์ด ๋ ์ํฐํฐ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ ์ํ๊ณ ์์ด. ์ด๋ ๊ฒ ํ๋ฉด Hibernate๊ฐ ์์์ ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํด์ค!
๋ค๋๋ค(Many-to-Many) ๊ด๊ณ
์ด๋ฒ์ ํ์๊ณผ ๊ณผ๋ชฉ ์ฌ์ด์ ๊ด๊ณ๋ฅผ ์๊ฐํด๋ณด์. ํ ํ์์ด ์ฌ๋ฌ ๊ณผ๋ชฉ์ ์๊ฐํ ์ ์๊ณ , ํ ๊ณผ๋ชฉ์ ์ฌ๋ฌ ํ์์ด ๋ฑ๋กํ ์ ์์ง?
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
// ์์ฑ์, getter, setter ๋ฑ
}
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
// ์์ฑ์, getter, setter ๋ฑ
}
@ManyToMany ์ ๋ ธํ ์ด์ ๊ณผ @JoinTable์ ์ฌ์ฉํด์ ๋ค๋๋ค ๊ด๊ณ๋ฅผ ํํํ์ด. Hibernate๊ฐ ์๋์ผ๋ก ์ค๊ฐ ํ ์ด๋ธ์ ๋ง๋ค์ด์ ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํด์ค ๊ฑฐ์ผ.
2. ์ฟผ๋ฆฌ ์์ฑํ๊ธฐ ๐
Hibernate๋ ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค. HQL, Criteria API, Native SQL ๋ฑ์ ์ฌ์ฉํ ์ ์์ด.
HQL (Hibernate Query Language)
HQL์ SQL๊ณผ ๋น์ทํ์ง๋ง ํ ์ด๋ธ๊ณผ ์ปฌ๋ผ ๋์ ์ํฐํฐ์ ์์ฑ์ ์ฌ์ฉํด.
String hql = "FROM User u WHERE u.username = :username";
Query query = session.createQuery(hql);
query.setParameter("username", "johndoe");
List<user> results = query.list();
</user>
Criteria API
Criteria API๋ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค. ํ์ ์์ ์ฑ์ ๋ณด์ฅํ๊ณ ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ ์ข์.
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<user> cr = cb.createQuery(User.class);
Root<user> root = cr.from(User.class);
cr.select(root).where(cb.equal(root.get("username"), "johndoe"));
Query<user> query = session.createQuery(cr);
List<user> results = query.getResultList();
</user></user></user></user>
Native SQL
๋ฐ์ดํฐ๋ฒ ์ด์ค ํน์ ๊ธฐ๋ฅ์ ์ฌ์ฉํด์ผ ํ ๋๋ Native SQL์ ์ฌ์ฉํ ์ ์์ด.
String sql = "SELECT * FROM users WHERE username = ?";
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(1, "johndoe");
query.addEntity(User.class);
List<user> results = query.list();
</user>
์ด๋ ๊ฒ ๋ค์ํ ์ฟผ๋ฆฌ ๋ฐฉ์์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์, ์ํฉ์ ๋ฐ๋ผ ๊ฐ์ฅ ์ ํฉํ ๋ฐฉ๋ฒ์ ์ ํํ ์ ์์ด. ๋ฉ์ง์ง ์์? ๐
3. ์บ์ฑ (Caching) ๐
Hibernate๋ ๊ฐ๋ ฅํ ์บ์ฑ ๊ธฐ๋ฅ์ ์ ๊ณตํด. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ์ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ง.
1์ฐจ ์บ์ (First-level Cache)
1์ฐจ ์บ์๋ ์ธ์ ์์ค์์ ์๋ํด. ๋์ผํ ์ธ์ ๋ด์์ ๊ฐ์ ์ํฐํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ์กฐํํ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋์ ์บ์์์ ๊ฐ์ ธ์.
2์ฐจ ์บ์ (Second-level Cache)
2์ฐจ ์บ์๋ ์ธ์ ํฉํ ๋ฆฌ ์์ค์์ ์๋ํด. ์ฌ๋ฌ ์ธ์ ์์ ๊ณต์ ํ ์ ์์ด ๋ ํฐ ์ฑ๋ฅ ํฅ์์ ๊ฐ์ ธ์ฌ ์ ์์ง.
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {
// ...
}
์ด๋ ๊ฒ @Cache ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ํด๋น ์ํฐํฐ๋ฅผ 2์ฐจ ์บ์์ ์ ์ฅํ ์ ์์ด. ์บ์ ์ ๋ต๋ ์ค์ ํ ์ ์์ง!
4. ๋ฐฐ์น ์ฒ๋ฆฌ (Batch Processing) ๐ฆ
๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋๋ ๋ฐฐ์น ์ฒ๋ฆฌ๊ฐ ํจ์จ์ ์ด์ผ. Hibernate๋ ์ด๋ฅผ ์ํ ์ฌ๋ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํด.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for (int i = 0; i < 100000; i++) {
User user = new User("user" + i, "user" + i + "@example.com");
session.save(user);
if (i % 50 == 0) { // 50๊ฐ ๋จ์๋ก ํ๋ฌ์
session.flush();
session.clear();
}
}
tx.commit();
session.close();
์ด๋ ๊ฒ ์ฃผ๊ธฐ์ ์ผ๋ก flush()์ clear()๋ฅผ ํธ์ถํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ด.
5. ์ด๋ฒคํธ์ ์ธํฐ์ ํฐ (Events and Interceptors) ๐ญ
Hibernate๋ ๋ค์ํ ์ด๋ฒคํธ๋ฅผ ์ ๊ณตํ๊ณ , ์ด๋ฅผ ์ธํฐ์ ํธํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํด. ์ด๋ฅผ ํตํด ์ํฐํฐ์ ์๋ช ์ฃผ๊ธฐ์ ๋ฐ๋ฅธ ์ปค์คํ ๋ก์ง์ ์ถ๊ฐํ ์ ์์ง.
public class AuditInterceptor extends EmptyInterceptor {
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
if (entity instanceof Auditable) {
for (int i = 0; i < propertyNames.length; i++) {
if ("createdAt".equals(propertyNames[i])) {
state[i] = new Date();
return true;
}
}
}
return false;
}
}
์ด๋ฐ ์ธํฐ์ ํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์ํฐํฐ๊ฐ ์ ์ฅ๋ ๋๋ง๋ค ์๋์ผ๋ก ์์ฑ ์๊ฐ์ ์ค์ ํ ์ ์์ด. ํธ๋ฆฌํ์ง?
์, ์ฌ๊ธฐ๊น์ง Hibernate์ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ์ดํด๋ดค์ด. ์ด๋, Hibernate๊ฐ ์ ๋ง ๊ฐ๋ ฅํ๋ค๋ ๊ฑธ ๋๊ผ์ง? ๐ ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ ์ ํ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ํจ์ฌ ๋ ํจ์จ์ ์ผ๋ก ํ ์ ์์ ๊ฑฐ์ผ. ๊ณ์ํด์ ํ์ตํ๊ณ ์ค์ตํด๋ณด๋ฉด์ Hibernate ๋ง์คํฐ๊ฐ ๋์ด๋ณด์!
๐ Hibernate ์ค์ ํ๊ณผ ์ฃผ์์ฌํญ ๐
์, ์ด์ Hibernate๋ฅผ ์ค์ ํ๋ก์ ํธ์์ ์ฌ์ฉํ ๋ ์์๋๋ฉด ์ข์ ํ๋ค๊ณผ ์ฃผ์ํด์ผ ํ ์ ๋ค์ ์์๋ณผ๊น? ์ด ๋ถ๋ถ์ ์ ๋ง ์ค์ํ๋๊น ์ง์คํด์ ๋ค์ด๋ด! ๐
1. N+1 ๋ฌธ์ ์ฃผ์ํ๊ธฐ โ ๏ธ
N+1 ๋ฌธ์ ๋ Hibernate๋ฅผ ์ฌ์ฉํ ๋ ์์ฃผ ๋ฐ์ํ๋ ์ฑ๋ฅ ์ด์์ผ. ์๋ฅผ ๋ค์ด, 100๊ฐ์ ๊ฒ์๊ธ๊ณผ ๊ฐ ๊ฒ์๊ธ์ ์์ฑ์๋ฅผ ๊ฐ์ ธ์ค๋ ค๊ณ ํ ๋, 101๋ฒ์ ์ฟผ๋ฆฌ๊ฐ ์คํ๋ ์ ์์ด.
List<post> posts = session.createQuery("from Post").list();
for (Post post : posts) {
System.out.println(post.getAuthor().getName()); // ์ฌ๊ธฐ์ ์ถ๊ฐ ์ฟผ๋ฆฌ ๋ฐ์!
}
</post>
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์๋ fetch join์ ์ฌ์ฉํ๊ฑฐ๋, @BatchSize ์ ๋ ธํ ์ด์ ์ ํ์ฉํ ์ ์์ด:
List<post> posts = session.createQuery("from Post p join fetch p.author").list();
</post>
2. ์ ์ ํ Fetch ์ ๋ต ์ ํํ๊ธฐ ๐ฏ
์ฐ๊ด ๊ด๊ณ์์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๊ฐ์ ธ์ฌ์ง ๊ฒฐ์ ํ๋ Fetch ์ ๋ต์ ์ฑ๋ฅ์ ํฐ ์ํฅ์ ๋ฏธ์ณ. EAGER์ LAZY ๋ ๊ฐ์ง๊ฐ ์๋๋ฐ, ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ์ ํํด์ผ ํด.
@Entity
public class Post {
@ManyToOne(fetch = FetchType.LAZY)
private User author;
// ...
}
์ผ๋ฐ์ ์ผ๋ก @ManyToOne์ ๊ธฐ๋ณธ์ด EAGER์ธ๋ฐ, ๋๋ถ๋ถ์ ๊ฒฝ์ฐ LAZY๋ก ์ค์ ํ๋ ๊ฒ์ด ์ข์. ํ์ํ ๋๋ง ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋๊น ์ฑ๋ฅ์ ์ด์ ์ด ์์ง.
3. ํธ๋์ญ์ ๊ด๋ฆฌ์ ์ ๊ฒฝ ์ฐ๊ธฐ ๐ผ
ํธ๋์ญ์ ๊ด๋ฆฌ๋ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ํด ๋งค์ฐ ์ค์ํด. ํนํ ์ฌ๋ฌ ์์ ์ ํ๋์ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ด์ผ ํ ๋ ์ฃผ์๊ฐ ํ์ํด.
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์
์ํ
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
ํธ๋์ญ์ ์ ํญ์ try-catch ๋ธ๋ก์ผ๋ก ๊ฐ์ธ๊ณ , ์์ธ ๋ฐ์ ์ ๋กค๋ฐฑํ๋ ๊ฒ์ ์์ง ๋ง!
4. ๋ฒ์ ๊ด๋ฆฌ ํ์ฉํ๊ธฐ ๐
๋์์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Hibernate์ ๋ฒ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์์ด.
@Entity
public class Product {
@Id
private Long id;
private String name;
@Version
private Integer version;
// ...
}
@Version ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด Hibernate๊ฐ ์๋์ผ๋ก ๋๊ด์ ์ ๊ธ(Optimistic Locking)์ ๊ตฌํํด์ค. ๋์ ์์ ์ผ๋ก ์ธํ ๋ฐ์ดํฐ ๋ถ์ผ์น๋ฅผ ๋ฐฉ์งํ ์ ์์ง.
5. ์ ์ ํ ID ์์ฑ ์ ๋ต ์ ํํ๊ธฐ ๐
ID ์์ฑ ์ ๋ต์ ์ฑ๋ฅ๊ณผ ํ์ฅ์ฑ์ ์ํฅ์ ๋ฏธ์น ์ ์์ด. ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ์ ๋ต์ ์ ํํด์ผ ํด.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ...
}
IDENTITY, SEQUENCE, TABLE ๋ฑ ๋ค์ํ ์ ๋ต์ด ์๋๋ฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํน์ฑ๊ณผ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ตฌ์ฌํญ์ ๊ณ ๋ คํด์ ์ ํํด์ผ ํด.
6. ์ ์ ํ ์บ์ ์ค์ ํ๊ธฐ ๐
์บ์๋ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ง๋ง, ์๋ชป ์ฌ์ฉํ๋ฉด ์คํ๋ ค ๋ฌธ์ ๊ฐ ๋ ์ ์์ด. ์บ์ ์ ๋ต์ ์ ์คํ๊ฒ ์ ํํด์ผ ํด.
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {
// ...
}
์์ฃผ ๋ณ๊ฒฝ๋์ง ์๋ ๋ฐ์ดํฐ๋ READ_ONLY, ์์ฃผ ๋ณ๊ฒฝ๋๋ ๋ฐ์ดํฐ๋ READ_WRITE ์ ๋ต์ ์ฌ์ฉํ๋ ๊ฒ ์ผ๋ฐ์ ์ด์ผ. ํ์ง๋ง ํญ์ ์ํฉ์ ๋ง๊ฒ ํ๋จํด์ผ ํด!
7. ์ฟผ๋ฆฌ ์ต์ ํํ๊ธฐ ๐
๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋๋ ์ฑ๋ฅ ์ต์ ํ์ ์ ๊ฒฝ ์จ์ผ ํด. Hibernate๊ฐ ์์ฑํ๋ SQL์ ๋ชจ๋ํฐ๋งํ๊ณ , ํ์ํ๋ค๋ฉด ์ง์ ์ต์ ํ๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด์ผ ํ ์๋ ์์ด.
String hql = "SELECT p FROM Product p JOIN FETCH p.category WHERE p.price > :price";
Query<product> query = session.createQuery(hql, Product.class);
query.setParameter("price", 100.0);
List<product> products = query.getResultList();
</product></product>
JOIN FETCH๋ฅผ ์ฌ์ฉํ๋ฉด N+1 ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๊ณ , ํ์ํ ๋ฐ์ดํฐ๋ง ์ ํ์ ์ผ๋ก ๊ฐ์ ธ์ค๋ฉด ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ด.
8. ์ํฐํฐ ์ํ ์ดํดํ๊ธฐ ๐
Hibernate์์ ์ํฐํฐ์ ์ํ(transient, persistent, detached)๋ฅผ ์ดํดํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํด. ๊ฐ ์ํ์ ๋ฐ๋ผ Hibernate์ ๋์์ด ๋ฌ๋ผ์ง๊ฑฐ๋ .
User user = new User(); // transient ์ํ
session.save(user); // persistent ์ํ๋ก ๋ณ๊ฒฝ
session.close(); // detached ์ํ๋ก ๋ณ๊ฒฝ
ํนํ detached ์ํ์ ์ํฐํฐ๋ฅผ ๋ค์ persistent ์ํ๋ก ๋ง๋ค ๋๋ merge()๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๊ฑธ ๊ธฐ์ตํด!
์, ์ฌ๊ธฐ๊น์ง Hibernate๋ฅผ ์ฌ์ฉํ ๋ ์์๋๋ฉด ์ข์ ํ๋ค๊ณผ ์ฃผ์์ฌํญ๋ค์ ์ดํด๋ดค์ด. ์ด๋ฐ ์ ๋ค์ ์ ๊ธฐ์ตํ๊ณ ์ ์ฉํ๋ค๋ฉด, Hibernate๋ฅผ ํจ์ฌ ๋ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ ๊ฑฐ์ผ. ๊ณ์ํด์ ์ค์ตํ๊ณ ๊ฒฝํ์ ์์๊ฐ๋ฉด์ Hibernate ์ ๋ฌธ๊ฐ๊ฐ ๋์ด๋ณด์! ํ์ดํ ! ๐ช
๐ญ Hibernate vs JPA: ์ฐจ์ด์ ๊ณผ ๊ด๊ณ ๐ญ
์, ์ด์ ๋ง์ ์ฌ๋๋ค์ด ํท๊ฐ๋ คํ๋ Hibernate์ JPA์ ๊ด๊ณ์ ๋ํด ์์๋ณผ๊น? ์ด ๋์ ์ฐจ์ด์ ๊ณผ ๊ด๊ณ๋ฅผ ์ดํดํ๋ฉด ์๋ฐ ORM์ ํฐ ๊ทธ๋ฆผ์ ๋ณผ ์ ์์ ๊ฑฐ์ผ. ์ค๋น๋๋? ์์ํด๋ณด์! ๐
1. JPA๋ ๋ฌด์์ธ๊ฐ? ๐
JPA(Java Persistence API)๋ ์๋ฐ ์ง์์ ORM ํ์ค ๋ช ์ธ์ผ. ์ฆ, ์ธํฐํ์ด์ค์ ๋ชจ์์ด๋ผ๊ณ ๋ณผ ์ ์์ง.
- โ JPA๋ ์๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์ ์ํ API์ผ.
- โ JPA๋ ์ธํฐํ์ด์ค์ผ ๋ฟ, ์ค์ ๊ตฌํ์ฒด๊ฐ ์๋์ผ.
- โ JPA๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ๊ตฌํ์ฒด์ ์ข ์๋์ง ์๊ณ ORM์ ์ฌ์ฉํ ์ ์์ด.
2. Hibernate์ JPA์ ๊ด๊ณ ๐ค
Hibernate๋ JPA์ ๊ตฌํ์ฒด ์ค ํ๋์ผ. ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๊ตฌํ์ฒด์ด๊ธฐ๋ ํ์ง.
- โ Hibernate๋ JPA ๋ช ์ธ๋ฅผ ๊ตฌํํ ORM ํ๋ ์์ํฌ์ผ.
- โ JPA๋ฅผ ์ฌ์ฉํ๋ฉด์ Hibernate์ ํน์ ๊ธฐ๋ฅ๋ ํ์ฉํ ์ ์์ด.
- โ Hibernate๋ JPA ์ด์ธ์๋ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํด.
3. ์ฃผ์ ์ฐจ์ด์ ๐
Hibernate์ JPA๋ ๋ฐ์ ํ ๊ด๊ณ์ด์ง๋ง, ๋ช ๊ฐ์ง ์ค์ํ ์ฐจ์ด์ ์ด ์์ด:
JPA | Hibernate |
---|---|
ํ์ค ๋ช ์ธ (์ธํฐํ์ด์ค) | JPA์ ๊ตฌํ์ฒด |
javax.persistence ํจํค์ง ์ฌ์ฉ | org.hibernate ํจํค์ง ์ฌ์ฉ |
EntityManagerFactory, EntityManager ์ฌ์ฉ | SessionFactory, Session ์ฌ์ฉ (JPA ์ธํฐํ์ด์ค๋ ๊ตฌํ) |
JPQL (Java Persistence Query Language) ์ฌ์ฉ | HQL (Hibernate Query Language) ์ฌ์ฉ (JPQL์ superset) |
4. ์ฝ๋๋ก ๋ณด๋ ์ฐจ์ด ๐ป
JPA์ Hibernate๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๋ฅผ ๋น๊ตํด๋ณผ๊น?
JPA ์ฌ์ฉ ์์:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
User user = new User("John Doe", "john@example.com");
em.persist(user);
em.getTransaction().commit();
em.close();
emf.close();
Hibernate ์ฌ์ฉ ์์:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
User user = new User("John Doe", "john@example.com");
session.save(user);
session.getTransaction().commit();
session.close();
sessionFactory.close();
๋ณด์ด๋ ๊ฒ์ฒ๋ผ, ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ๋น์ทํ์ง๋ง ์ฌ์ฉํ๋ ํด๋์ค์ ๋ฉ์๋ ์ด๋ฆ์ด ๋ค๋ฅด์ง?
5. ์ด๋ค ๊ฒ์ ์ ํํด์ผ ํ ๊น? ๐ค
๊ทธ๋์ ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ค ๊ฒ์ ์ ํํด์ผ ํ ๊น?
- โ JPA๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์: ํน์ ๊ตฌํ์ฒด์ ์ข ์๋์ง ์๊ณ , ๋์ค์ ๋ค๋ฅธ ๊ตฌํ์ฒด๋ก ์ฝ๊ฒ ์ ํํ ์ ์์ด.
- โ ํ์ง๋ง Hibernate์ ํน์ ๊ธฐ๋ฅ์ด ํ์ํ๋ค๋ฉด, JPA๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ฉด์ ํ์ํ ๋ถ๋ถ๋ง Hibernate API๋ฅผ ์ฌ์ฉํ ์ ์์ด.
- โ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ JPA๋ง์ผ๋ก๋ ์ถฉ๋ถํด. Spring Data JPA ๊ฐ์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์ฝ๊ฒ ORM์ ํ์ฉํ ์ ์์ง.
์, ์ฌ๊ธฐ๊น์ง Hibernate์ JPA์ ๊ด๊ณ์ ์ฐจ์ด์ ์ ๋ํด ์์๋ดค์ด. ์ด๋, ์ด์ ๋์ ๊ด๊ณ๊ฐ ์ข ๋ ๋ช ํํด์ก์ง? ๐ค ์ด ์ง์์ ๋ฐํ์ผ๋ก ํ๋ก์ ํธ์ ๊ฐ์ฅ ์ ํฉํ ๋ฐฉ์์ ์ ํํ ์ ์์ ๊ฑฐ์ผ. ๊ณ์ํด์ ํ์ตํ๊ณ ๊ฒฝํ์ ์์๊ฐ๋ฉด์ ORM์ ๋ฌ์ธ์ด ๋์ด๋ณด์! ํ์ดํ ! ๐ช
๐ Hibernate์ ๋ฏธ๋์ ๋ฐ์ ๋ฐฉํฅ ๐
์, ์ด์ ์ฐ๋ฆฌ์ Hibernate ์ฌํ๋ ๊ฑฐ์ ๋๋๊ฐ๊ณ ์์ด. ํ์ง๋ง Hibernate์ ์ฌ์ ์ ์ฌ๊ธฐ์ ๋์ด ์๋์ผ. ๋ฏธ๋์๋ ์ด๋ค ๋ชจ์ต์ผ๋ก ๋ฐ์ ํ ์ง, ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ์ด๋ป๊ฒ ์ค๋นํด์ผ ํ ์ง ํจ๊ป ์์๋ณด์! ๐ฎ
1. ํด๋ผ์ฐ๋ ๋ค์ดํฐ๋ธ ์ง์ ๊ฐํ โ๏ธ
ํด๋ผ์ฐ๋ ์ปดํจํ ์ด ๋์ธ๊ฐ ๋๋ฉด์, Hibernate๋ ์ด์ ๋ฐ๋ง์ถฐ ๋ณํํ๊ณ ์์ด.
- โ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ์ ์ต์ ํ๋ ๊ธฐ๋ฅ ์ถ๊ฐ
- โ ์ปจํ ์ด๋ํ๋ ํ๊ฒฝ์์์ ์ฑ๋ฅ ์ต์ ํ
- โ ์๋ฒ๋ฆฌ์ค ํ๊ฒฝ ์ง์ ๊ฐํ
2. ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ ์ง์ ๐
๋น๋๊ธฐ ์ฒ๋ฆฌ์ ๋ ผ๋ธ๋กํน I/O์ ์ค์์ฑ์ด ์ปค์ง๋ฉด์, Hibernate๋ ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๊ธฐ ์์ํ์ด.
- โ Hibernate Reactive ํ๋ก์ ํธ ์งํ ์ค
- โ ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋๋ผ์ด๋ฒ ์ง์
- โ ๋ฆฌ์กํฐ๋ธ ์คํธ๋ฆผ API์์ ํตํฉ
// ๋ฏธ๋์ Hibernate Reactive ์ฌ์ฉ ์์
Uni<User> user = session.find(User.class, userId);
user.onItem().transform(u -> {
u.setLastLoginDate(LocalDateTime.now());
return u;
})
.call(u -> session.flush());
3. ๋ ์ค๋งํธํ ์ฟผ๋ฆฌ ์ต์ ํ ๐ง
์ธ๊ณต์ง๋ฅ๊ณผ ๋จธ์ ๋ฌ๋ ๊ธฐ์ ์ ๋ฐ์ ์ผ๋ก, Hibernate์ ์ฟผ๋ฆฌ ์ต์ ํ ๊ธฐ๋ฅ๋ ๋ ์ฑ ์ค๋งํธํด์ง ๊ฑฐ์ผ.
- โ AI ๊ธฐ๋ฐ์ ์ฟผ๋ฆฌ ๋ถ์๊ณผ ์๋ ์ต์ ํ
- โ ์ฌ์ฉ ํจํด์ ํ์ตํ์ฌ ์์ธก์ ์บ์ฑ ๊ตฌํ
- โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํน์ฑ์ ๋ฐ๋ฅธ ์๋ ์ธ๋ฑ์ค ์ถ์ฒ
4. ๋ค์ํ ๋ฐ์ดํฐ ๋ชจ๋ธ ์ง์ ๐
๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฟ๋ง ์๋๋ผ ๋ค์ํ ์ ํ์ ๋ฐ์ดํฐ ์ ์ฅ์๋ฅผ ์ง์ํ๋ ๋ฐฉํฅ์ผ๋ก ๋ฐ์ ํ ๊ฑฐ์ผ.
- โ NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ํตํฉ ๊ฐํ
- โ ๊ทธ๋ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ง์
- โ ์๊ณ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ต์ ํ
// ๋ฏธ๋์ Hibernate ๋ฉํฐ๋ชจ๋ธ ์ง์ ์์
@Entity
@NoSQL(type = "document")
public class User {
@Id
private String id;
@GraphRelation(type = "FRIENDS")
private List<User> friends;
@TimeSeriesData
private List<LoginEvent> loginHistory;
}
5. ๋ ๊ฐ๋ ฅํ ํ์ ์์ ์ฑ ๐ก๏ธ
Java์ ํ์ ์์คํ ์ด ๋ฐ์ ํจ์ ๋ฐ๋ผ, Hibernate๋ ๋ ๊ฐ๋ ฅํ ํ์ ์์ ์ฑ์ ์ ๊ณตํ ๊ฑฐ์ผ.
- โ ์ปดํ์ผ ํ์ ์ฟผ๋ฆฌ ๊ฒ์ฆ ๊ฐํ
- โ ์ ๋ค๋ฆญ์ ํ์ฉํ ํ์ ์์ ์ฟผ๋ฆฌ ๋น๋
- โ Null ์์ ์ฑ ๊ฐ์
// ๋ฏธ๋์ ํ์
์์ ์ฟผ๋ฆฌ ์์
TypedQuery<User> query = session.createTypedQuery(User.class)
.where(User::getAge).greaterThan(18)
.and(User::getStatus).eq(UserStatus.ACTIVE);
List<User> users = query.getResultList();
6. ๋ ์ฌ์ด ํ์ต ๊ณก์ ๐
Hibernate์ ๋ณต์ก์ฑ์ ์ค์ด๊ณ , ์ด๋ณด์๋ ์ฝ๊ฒ ์ ๊ทผํ ์ ์๋๋ก ๋ฐ์ ํ ๊ฑฐ์ผ.
- โ ์๋ ์ค์ ๊ธฐ๋ฅ ๊ฐํ
- โ ๋ ์ง๊ด์ ์ธ API ๋์์ธ
- โ ํตํฉ ๊ฐ๋ฐ ํ๊ฒฝ(IDE)๊ณผ์ ๊ธด๋ฐํ ์ฐ๋
7. ์ฑ๋ฅ๊ณผ ํ์ฅ์ฑ์ ๊ทน๋ํ ๐
๋ ํฐ ๊ท๋ชจ์ ๋ฐ์ดํฐ์ ํธ๋ํฝ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ฑ๋ฅ๊ณผ ํ์ฅ์ฑ์ด ๊ฐ์ ๋ ๊ฑฐ์ผ.
- โ ๋ถ์ฐ ์บ์ฑ ๋ฉ์ปค๋์ฆ ๊ฐํ
- โ ์ค๋ฉ๊ณผ ํํฐ์ ๋ ์ง์ ๊ฐ์
- โ ๋น ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ์คํธ๋ฆฌ๋ฐ ์ฟผ๋ฆฌ ์ง์
// ๋ฏธ๋์ Hibernate ๋ถ์ฐ ์ฒ๋ฆฌ ์์
@Sharded(shardKey = "userId")
@Entity
public class UserActivity {
@Id
private String id;
@PartitionKey
private LocalDate date;
@StreamQuery
public static Stream<UserActivity> findRecentActivities(String userId) {
// ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ์ต๊ทผ ํ๋ ์กฐํ
}
}
์, ์ฌ๊ธฐ๊น์ง Hibernate์ ๋ฏธ๋์ ๋ฐ์ ๋ฐฉํฅ์ ๋ํด ์์๋ดค์ด. ์ด๋, ๋ฏธ๋๊ฐ ๊ธฐ๋๋์ง ์์? ๐ Hibernate๋ ๊ณ์ํด์ ์งํํ๊ณ ์๊ณ , ์ฐ๋ฆฌ๋ ํจ๊ป ์ฑ์ฅํด ๋๊ฐ์ผ ํด. ์๋ก์ด ๊ธฐ์ ๊ณผ ํธ๋ ๋๋ฅผ ํญ์ ์ฃผ์ํ๋ฉด์, ๋์์์ด ํ์ตํ๋ ์์ธ๊ฐ ์ค์ํด. ํจ๊ป Hibernate์ ๋ฏธ๋๋ฅผ ๋ง๋ค์ด๊ฐ๋ ์ฃผ์ธ๊ณต์ด ๋์ด๋ณด์! ํ์ดํ ! ๐ช
๐ Hibernate ๋ง์คํฐ๊ฐ ๋๊ธฐ ์ํ ๋ก๋๋งต ๐
์, ์ด์ ์ฐ๋ฆฌ์ Hibernate ์ฌํ๋ ๋ง๋ฐ์ง์ ์ ์ด๋ค์์ด. ํ์ง๋ง ์ด๊ฒ ๋์ด ์๋์ผ. Hibernate ๋ง์คํฐ๊ฐ ๋๊ธฐ ์ํ ์ฌ์ ์ ์ด์ ๋ถํฐ ์์์ด์ผ! ์ด๋ป๊ฒ ํ๋ฉด Hibernate ์ ๋ฌธ๊ฐ๊ฐ ๋ ์ ์์์ง, ๊ทธ ๋ก๋๋งต์ ํจ๊ป ์ดํด๋ณด์. ์ค๋น๋๋? ์ถ๋ฐ! ๐
1. ๊ธฐ์ด ๋ค์ง๊ธฐ ๐๏ธ
- โ Java ๊ธฐ์ด๋ฅผ ํํํ ํ๊ธฐ
- โ SQL๊ณผ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ๋ ๋ง์คํฐํ๊ธฐ
- โ JPA ๊ธฐ๋ณธ ๊ฐ๋ ์ดํดํ๊ธฐ
- โ Hibernate ํต์ฌ ๊ฐ๋ ํ์ตํ๊ธฐ (์ํฐํฐ, ์ธ์ , ํธ๋์ญ์ ๋ฑ)
2. ์ค์ ํ๋ก์ ํธ ๊ฒฝํ ์๊ธฐ ๐ ๏ธ
- โ ๊ฐ๋จํ CRUD ์ ํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ
- โ Spring Boot์ Hibernate ํตํฉ ํ๋ก์ ํธ ์งํํ๊ธฐ
- โ ๋ณต์กํ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๊ฐ์ง ํ๋ก์ ํธ ๊ตฌํํด๋ณด๊ธฐ
- โ ์ฑ๋ฅ ์ต์ ํ ๊ฒฝํ ์๊ธฐ
// ์ค์ ํ๋ก์ ํธ ์์: ๋ธ๋ก๊ทธ ์์คํ
๊ตฌํ
@Entity
public class BlogPost {
@Id @GeneratedValue
private Long id;
private String title;
@Lob
private String content;
@ManyToOne
private User author;
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();
// ์์ฑ์, getter, setter ๋ฑ
}
3. ๊ณ ๊ธ ๊ธฐ๋ฅ ๋ง์คํฐํ๊ธฐ ๐ฏ
- โ ์บ์ฑ ๋ฉ์ปค๋์ฆ ๊น์ด ์ดํดํ๊ธฐ
- โ ์ฟผ๋ฆฌ ์ต์ ํ ๊ธฐ๋ฒ ์ตํ๊ธฐ
- โ ๋ฐฐ์น ์ฒ๋ฆฌ ๊ตฌํํด๋ณด๊ธฐ
- โ ๋์์ฑ ์ ์ด ๋ฐฉ๋ฒ ํ์ตํ๊ธฐ
4. ์ฑ๋ฅ ํ๋ ์ ๋ฌธ๊ฐ ๋๊ธฐ ๐
- โ ํ๋กํ์ผ๋ง ๋๊ตฌ ์ฌ์ฉ๋ฒ ์ตํ๊ธฐ
- โ N+1 ๋ฌธ์ ํด๊ฒฐ ๋ฐฉ๋ฒ ๋ง์คํฐํ๊ธฐ
- โ ์ธ๋ฑ์ฑ ์ ๋ต ์๋ฆฝํ๊ธฐ
- โ ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ธฐ๋ฒ ํ์ตํ๊ธฐ
// ์ฑ๋ฅ ์ต์ ํ ์์: N+1 ๋ฌธ์ ํด๊ฒฐ
@Query("SELECT p FROM Post p JOIN FETCH p.comments WHERE p.author.id = :authorId")
List<Post> findPostsWithCommentsByAuthor(@Param("authorId") Long authorId);
5. ์ปค๋ฎค๋ํฐ ์ฐธ์ฌ์ ์ง์ ๊ณต์ ๐
- โ Stack Overflow์์ ์ง๋ฌธํ๊ณ ๋ต๋ณํ๊ธฐ
- โ GitHub์์ ์คํ ์์ค ํ๋ก์ ํธ์ ๊ธฐ์ฌํ๊ธฐ
- โ ๊ธฐ์ ๋ธ๋ก๊ทธ ์ด์ํ๊ธฐ
- โ ์ปจํผ๋ฐ์ค๋ ๋ฐ์ ์ฐธ์ํ๊ธฐ
6. ์ต์ ํธ๋ ๋ ๋ฐ๋ผ๊ฐ๊ธฐ ๐
- โ Hibernate ๊ณต์ ๋ฌธ์ ์ ๊ธฐ์ ์ผ๋ก ํ์ธํ๊ธฐ
- โ Java์ ORM ๊ด๋ จ ์ปจํผ๋ฐ์ค ์์ ์์ฒญํ๊ธฐ
- โ ๊ธฐ์ ๋ด์ค๋ ํฐ ๊ตฌ๋ ํ๊ธฐ
- โ ์๋ก์ด ๋ฒ์ ์ ํน์ง ํ์ตํ๊ณ ์ ์ฉํด๋ณด๊ธฐ
7. ๊ด๋ จ ๊ธฐ์ ์ตํ๊ธฐ ๐ง
- โ Spring Framework ๊น์ด ์๊ฒ ํ์ตํ๊ธฐ
- โ Docker์ Kubernetes ๊ธฐ์ด ์ตํ๊ธฐ
- โ NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฒฝํํด๋ณด๊ธฐ
- โ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ ์ดํดํ๊ธฐ
์, ์ฌ๊ธฐ๊น์ง๊ฐ Hibernate ๋ง์คํฐ๊ฐ ๋๊ธฐ ์ํ ๋ก๋๋งต์ด์ผ. ์ด๋, ๊ฝค ๊ธด ์ฌ์ ์ด์ง? ๐ ํ์ง๋ง ๊ฑฑ์ ํ์ง ๋ง. ํ ๋ฒ์ ๋ค ํ ํ์๋ ์์ด. ์ฒ์ฒํ, ๊พธ์คํ ๋์๊ฐ๋ค ๋ณด๋ฉด ์ด๋์ Hibernate ์ ๋ฌธ๊ฐ๊ฐ ๋์ด ์์ ๊ฑฐ์ผ.
๊ธฐ์ตํด, ํ์ต์ ๋์ ์์ด. Hibernate ๋ง์คํฐ๊ฐ ๋ ํ์๋ ๊ณ์ํด์ ์๋ก์ด ๊ฒ์ ๋ฐฐ์ฐ๊ณ ์ฑ์ฅํด ๋๊ฐ์ผ ํด. ๊ทธ๊ฒ ๋ฐ๋ก ์ง์ ํ ์ ๋ฌธ๊ฐ์ ์์ธ์ผ. ํจ๊ป ์ฑ์ฅํด ๋๊ฐ์! ํ์ดํ ! ๐ช
๊ด๋ จ ํค์๋
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ