객체와 관계형 데이터베이스 간의 매핑을 자동화하는 프로그래밍 기법
개발자가 직접 SQL 쿼리를 작성하지 않고도 객체 지향 코드에서 관계형 데이터베이스에 접근
- 객체-관계 매핑: ORM은 개체와 테이블 간의 매핑을 제공합니다. 클래스를 테이블로, 객체를 레코드로, 속성을 열로 매핑하여 개체 모델과 데이터베이스 스키마 간의 일치를 달성
- CRUD 작업: ORM은 생성(Create), 조회(Read), 갱신(Update), 삭제(Delete) 작업에 대한 추상화 계층을 제공하여 개발자가 데이터베이스와 상호작용할 때 객체 지향적인 인터페이스를 사용할 수 있도록 함
- 지연 로딩 및 즉시 로딩: ORM은 연관된 객체들을 필요한 시점에 로드하는 지연 로딩(Lazy Loading)과 한 번에 모든 연관된 객체들을 즉시 로드하는 즉시 로딩(Eager Loading) 기능을 제공합니다.
- 캐싱: ORM은 자주 액세스되는 데이터나 쿼리 결과를 메모리 내의 캐시에 저장하여 성능 향상
- 트랜잭션 관리: ORM은 트랜잭션 관리 기능을 제공하여 일관된 상태 유지와 데이터베이스 변경의 원자성 보장 등과 같은 ACID 원칙을 준수
Hibernate
- Mapping Class
<!-- pom.xml -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.5.7.Final</version> <!-- 사용하는 Hibernate 버전에 맞게 변경 -->
</dependency>
<!-- hibernate.cfg.xml -->
<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">username</property>
<property name="hibernate.connection.password">password</property>
<!-- Hibernate Dialect 설정 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 매핑 클래스 설정 -->
<mapping class="com.example.User"/>
</session-factory>
</hibernate-configuration>
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "username")
private String username;
@Column(name = "email")
private String email;
// 생성자, getter 및 setter 메서드
}
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Main {
public static void main(String[] args) {
// Hibernate 설정 로드
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
try (SessionFactory sessionFactory = configuration.buildSessionFactory()) {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
try {
// Create operation
Employee employee1 = new Employee();
employee1.setFirstName("John");
session.save(employee1);
Long employee2ID =(Long ) session.save(employee2);
session.flush(); // 변경 내용 반영
// Read operation
Employee savedEmployee= session.get(Employee.class, employee2ID );
System.out.println(savedEmployee.getFirstName());
// Update operation
savedEmployee.setFirstName("Jane");
session.update(savedEmployee);
session.flush(); // 변경 내용 반영
// Delete operation
session.delete(savedEmployee);
session.flush(); // 변경 내용 반영
} catch(Exception e){
transaction.rollback();
e.printStackTrace();
}
}
}
}
- Mapping File
<!-- hibernate.cfg.xml -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
<property name="connection.username">your_username_here</property>
<property name="connection.password">your_password_here</property>
<!-- Mapping file -->
<mapping resource="Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
public class Employee {
private Long id;
private String firstName;
private String lastName;
// Getters and setters
}
<!-- Employee.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example.model">
<class name="Employee" table="employees">
<id name="id" column="employee_id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
</class>
</hibernate-mapping>
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Main {
public static void main(String[] args) {
// Hibernate 설정 로드
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
try (SessionFactory sessionFactory = configuration.buildSessionFactory()) {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
try {
// Create operation
Employee employee1 = new Employee();
employee1.setFirstName("John");
employee1.setLastName("Doe");
Long employeeId = (Long) session.save(employee1);
System.out.println("Employee ID: " + employeeId);
// Read operation
Employee savedEmployee = session.get(Employee.class, employeeId);
System.out.println("First Name: " + savedEmployee.getFirstName());
System.out.println("Last Name: " + savedEmployee.getLastName());
// Update operation
savedEmployee.setFirstName("Jane");
session.update(savedEmployee);
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
}
}
}
}
iBatis
- Mapping file
<!-- pom.xml -->
<dependencies>
<!-- iBATIS Core -->
<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-core</artifactId>
<version>3.0.6</version>
</dependency>
<!-- Oracle JDBC Driver -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>{ojdbc_version}</version>
</dependency>
</dependencies>
public class Employee {
private Long id;
private String firstName;
private String lastName;
// Getters and setters
}
<!-- Employee.xml -->
<!DOCTYPE mapper PUBLIC "-//iBATIS.com//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="com.example.dao.EmployeeDao">
<!-- CREATE -->
<insert id="createEmployee" parameterType="com.example.model.Employee">
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (#{id}, #{firstName}, #{lastName})
</insert>
<!-- READ -->
<select id="getEmployeeById" parameterType="java.lang.Long" resultType="com.example.model.Employee">
SELECT * FROM employees WHERE employee_id = #{id}
</select>
<!-- UPDATE -->
<update id="updateEmployee" parameterType="com.example.model.Employee">
UPDATE employees SET first_name = #{firstName}, last_name = #{lastName}
WHERE employee_id = #{id}
</update>
<!-- DELETE -->
<delete id="deleteEmployeeById" parameterType="java.lang.Long">
DELETE FROM employees WHERE employee_id = #{id}
</delete>
</mapper>
public interface EmployeeDao {
void createEmployee(Employee employee);
Employee getEmployeeById(Long id);
void updateEmployee(Employee employee);
void deleteEmployeeById(Long id);
}
public class EmployeeDaoImpl implements EmployeeDao {
private SqlSessionFactory sqlSessionFactory;
public EmployeeDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public void createEmployee(Employee employee) {
try (SqlSession session = sqlSessionFactory.openSession()) {
session.insert("com.example.dao.EmployeeDao.createEmployee", employee);
session.commit();
}
}
@Override
public Employee getEmployeeById(Long id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
return session.selectOne("com.example.dao.EmployeeDao.getEmployeeById", id);
}
}
@Override
public void updateEmployee(Employee employee) {
try (SqlSession session = sqlSessionFactory.openSession()) {
session.update("com.example.dao.EmployeeDao.updateEmployee", employee);
session.commit();
}
}
@Override
public void deleteEmployeeById(Long id) {
try (SqlSession session = sqlSessionFactory.openSession()) {
session.delete("com.example.dao.EmployeeDao.deleteEmployeeById", id);
session.commit();
}
}
}
<!-- mybatis-config.xml -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- Database connection settings -->
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="username" value="{your_username_here}"/>
<property name="password" value="{your_password_here}"/>
</dataSource>
</environment>
</environments>
<!-- Mappers -->
<mappers>
<mapper resource="Employee.xml"/>
</mappers>
</configuration>
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
try {
// MyBatis 설정 파일 로드
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// EmployeeDao 인스턴스 생성
EmployeeDao employeeDao = new EmployeeDaoImpl(sqlSessionFactory);
// 데이터 생성
Employee employee1 = new Employee();
employee1.setId(1L);
employee1.setFirstName("John");
employee1.setLastName("Doe");
employeeDao.createEmployee(employee1);
// 데이터 조회
Long employeeId = 1L;
Employee employee = employeeDao.getEmployeeById(employeeId);
System.out.println("First Name: " + employee.getFirstName());
System.out.println("Last Name: " + employee.getLastName());
// 데이터 갱신
employee.setFirstName("Jane");
employeeDao.updateEmployee(employee);
// 데이터 삭제
employeeDao.deleteEmployeeById(employeeId);
} catch (IOException e) {
e.printStackTrace();
}
}
}
MyBatis
- Mapping file
<!-- pom.xml -->
<dependencies>
<!-- MyBatis Core -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- Oracle JDBC Driver -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>{ojdbc_version}</version>
</dependency>
</dependencies>
public class Employee {
private Long id;
private String firstName;
private String lastName;
// Getters and setters
}
public interface EmployeeMapper {
// CREATE
void createEmployee(Employee employee);
// READ
Employee getEmployeeById(Long id);
// UPDATE
void updateEmployee(Employee employee);
// DELETE
void deleteEmployeeById(Long id);
}
<!-- EmployeeMapper.xml -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.EmployeeMapper">
<!-- CREATE -->
<insert id="createEmployee" parameterType="com.example.model.Employee">
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (#{id}, #{firstName}, #{lastName})
</insert>
<!-- READ -->
<select id="getEmployeeById" parameterType="java.lang.Long" resultType="com.example.model.Employee">
SELECT * FROM employees WHERE employee_id = #{id}
</select>
<!-- UPDATE -->
<update id="updateEmployee" parameterType="com.example.model.Employee">
UPDATE employees SET first_name = #{firstName}, last_name = #{lastName}
WHERE employee_id = #{id}
</update>
<!-- DELETE -->
<delete id="deleteEmployeeById" parameterType="java.lang.Long">
DELETE FROM employees WHERE employee_id = #{id}
</delete>
</mapper>
<!-- mybatis-config.xml -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- Database connection settings -->
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="{jdbc_url}"/>
<property name="username" value="{username}"/>
<property name="password" value="{password}"/>
</dataSource>
</environment>
</environments>
<!-- Mappers -->
<mappers>
<mapper resource="{path_to_mapper_xml_file}/EmployeeMapper.xml"/>
</mappers>
</configuration>
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
try {
// MyBatis 설정 파일 로드
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// SqlSession 생성
try (SqlSession session = sqlSessionFactory.openSession()) {
// Mapper 인스턴스 생성
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
// 데이터 생성
Employee employee1 = new Employee();
employee1.setId(1L);
employee1.setFirstName("John");
employee1.setLastName("Doe");
employeeMapper.createEmployee(employee1);
// 데이터 조회
Long employeeId = 1L;
Employee employee = employeeMapper.getEmployeeById(employeeId);
System.out.println("First Name: " + employee.getFirstName());
System.out.println("Last Name: " + employee.getLastName());
// 데이터 갱신
employee.setFirstName("Jane");
employeeMapper.updateEmployee(employee);
// 데이터 삭제
employeeMapper.deleteEmployeeById(employeeId);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}