개요
이 가이드 에서는 최대 절전 모드 ORM용 MongoDB 확장을 사용하여 MongoDB 컬렉션에서 생성, 읽기, 업데이트 및 삭제 (CRUD ) 작업을 실행 방법을 학습 수 있습니다.
샘플 데이터
이 가이드 의 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix.movies 컬렉션 나타내는 Movie 엔터티를 사용합니다. Movie 엔터티의 정의는 다음과 같습니다.
import com.mongodb.hibernate.annotations.ObjectIdGenerator;import org.bson.types.ObjectId;import java.time.Instant;import java.util.List;import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;import jakarta.persistence.FetchType;import jakarta.persistence.Id;import jakarta.persistence.OneToMany;import jakarta.persistence.Table;
@Entity@Table(name = "movies")public class Movie { @Id @ObjectIdGenerator private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; @Embedded private Awards awards; @OneToMany(mappedBy = "movie", fetch = FetchType.LAZY) private List<Comment> comments;
public Movie(String title, String plot, int year, List<String> cast, List<String> directors, Instant released, Awards awards) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; this.directors = directors; this.released = released; this.awards = awards; }
public Movie() {
}
public ObjectId getId() { return id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getPlot() { return plot; }
public void setPlot(String plot) { this.plot = plot; }
public int getYear() { return year; }
public void setYear(int year) { this.year = year; }
public List<String> getCast() { return cast; }
public void setCast(List<String> cast) { this.cast = cast; }
public List<String> getDirectors() { return directors; }
public void setDirectors(List<String> directors) { this.directors = directors; }
public Awards getAwards() { return awards; }
public void setAwards(Awards awards) { this.awards = awards; }
public Instant getReleased() { return released; }
public void setReleased(Instant released) { this.released = released; }
public List<Comment> getComments() { return comments; }
public void setComments(List<Comment> comments) { this.comments = comments; }}최대 절전 모드용 MongoDB 확장 ORM을 사용하여 이 MongoDB 샘플 컬렉션과 상호 작용하는 Java 애플리케이션 만드는 방법을 학습하려면 시작하기 튜토리얼을 참조하세요.
중요
지속성 컨텍스트
하이버네이트 ORM이 데이터베이스 와 상호 작용 활성화 하려면 하이버네이트 Session 또는 자카르타 퍼시스턴스 EntityManager를 사용하여 퍼시스턴스 컨텍스트 내에서 작업을 실행 해야 합니다. 또한 트랜잭션 내에서 쓰기 (write) 작업을 실행 MongoDB 데이터를 수정하고 데이터 무결성을 유지해야 합니다.
이 가이드 의 예제를 실행 전에 다음 코드와 유사한 지속성 컨텍스트 및 트랜잭션 관리 코드를 애플리케이션 에 추가해야 합니다.
var sf = HibernateUtil.getSessionFactory();Session session = sf.openSession();Transaction tx = session.beginTransaction();
// ... Perform CRUD operations here
tx.commit();session.close();sf.close();세션을 사용하려면 SessionFactory를 구성하는 HibernateUtil.java 파일 만들어야 합니다. 자세히 학습 시작하기 튜토리얼의 애플리케이션 구성 단계를 참조하세요.
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin();
// ... Perform CRUD operations here
entityManager.getTransaction().commit();entityManager.close();emf.close;EntityManager를 사용하려면 지속성 단위를 선언하는 persistence.xml 파일 만들어야 합니다. 자세히 학습하려면 하이버네이트 ORM 문서에서 JPA 표준 API를 사용하는 튜토리얼 을 참조하세요.
문서 삽입
다음 메서드에 엔터티 인스턴스 전달하여 문서 생성하면 해당 문서 가 컬렉션 에 삽입됩니다.
org.hibernate.Session.persist(): 최대 절전 모드 API 사용하여 데이터베이스 에 변경 사항 적용jakarta.persistence.EntityManager.persist(): 자카르타 지속성 API 사용하여 데이터베이스 에 변경 사항 적용
팁
엔터티 인스턴스를 생성하고 이를 데이터베이스에 유지하는 방법에 대해 자세히 학습하려면 하이버네이트 ORM 사용자 가이드에서 엔터티를 영구화하기 를 참조하세요.
예시
다음 예시 새 Movie 엔터티 인스턴스 만들고 persist() 메서드를 사용하여 해당 문서 sample_mflix.movies 컬렉션 에 삽입합니다.
var myMovie = new Movie();myMovie.setTitle("Knives Out");myMovie.setYear(2019);myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans"));myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " + "unraveling lies as every Thrombey family member becomes a suspect.");session.persist(myMovie);var myMovie = new Movie();myMovie.setTitle("Knives Out");myMovie.setYear(2019);myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans"));myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " + "unraveling lies as every Thrombey family member becomes a suspect.");entityManager.persist(myMovie);문서 읽기
컬렉션 에서 문서를 조회 하려면 쿼리 기준을 createQuery() 메서드에 전달합니다. 다음 API는 모두 createQuery() 메서드를 제공합니다.
하이버네이트의
SessionAPI: 하이버네이트 쿼리 언어(HQL) 구문을 사용하여 쿼리 정의하기자카르타 퍼시스턴스의
EntityManagerAPI: HQL의 하위 집합인 자카르타 퍼시스턴스 쿼리 언어(JPQL) 구문을 사용하여 쿼리를 정의합니다.
팁
HQL 및 JPQL 구문을 사용하여 데이터를 검색하는 방법에 대해 자세히 학습하려면 하이버네이트 ORM 쿼리 가이드에서 문 선택 을 참조하세요.
참고
이 섹션에서는 HQL 및 JPQL을 사용하여 문서를 읽는 방법을 설명하지만, 기준 빌더 또는 네이티브 쿼리를 사용하여 데이터를 조회 할 수도 있습니다. 자세히 학습 다음 가이드를 참조하세요.
1개의 문서 반환 예제
쿼리 기준과 일치하는 문서 하나만 조회 하려면 getSingleResult() 메서드를 createQuery() 메서드에 연결합니다. 다음 예시 sample_mflix.movies 컬렉션 에서 title 값이 "Boyhood" 인 문서 하나를 검색합니다.
var singleResult = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Boyhood") .getSingleResult();System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());var singleResult = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Boyhood") .getSingleResult();System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());여러 문서 반환 예시
다음 예시 세션에서 createQuery() 메서드를 호출하여 sample_mflix.movies 컬렉션 에서 문서를 조회 . 이 코드는 HQL 및 JPQL을 사용하여 year 값이 1920 인 문서를 반환하고 해당 title 값을 출력합니다.
var results = session.createQuery("from Movie where year = :y", Movie.class) .setParameter("y", 1920) .getResultList();results.forEach(movie -> System.out.println(movie.getTitle()));var results = entityManager.createQuery("select m from Movie m where m.year = :y", Movie.class) .setParameter("y", 1920) .getResultList();results.forEach(movie -> System.out.println(movie.getTitle()));문서 수정
다음 작업을 수행하여 컬렉션 의 문서를 수정할 수 있습니다.
문서 하나 업데이트: 엔터티의 setter 메서드를 호출하여 엔터티 인스턴스 한 개의 필드 값을 변경한 다음 세션 또는 엔터티 관리자를 사용하여 변경 사항을 유지합니다.
여러 문서 업데이트: 세션 또는 엔티티 관리자의
createQuery()또는createMutationQuery()메서드에 업데이트 성명서 전달합니다. 그런 다음executeUpdate()메서드를 호출하여 데이터베이스 에 변경 사항을 적용 .
팁
최대 절전 모드 ORM을 사용하여 데이터를 수정하는 방법에 대해 자세히 학습 다음 리소스를 참조하세요.
하나의 예제 업데이트
다음 예시 ObjectId 값으로 문서 조회합니다. 그런 다음 Movie 엔터티의 setTitle() 메서드를 예시 하여 문서의 title 값을 "Jurassic Park I"로 업데이트 .
// Your ObjectId value might differMovie movieById = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));movieById.setTitle("Jurassic Park I");session.persist(movieById);// Your ObjectId value might differMovie movieById = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));movieById.setTitle("Jurassic Park I");entityManager.persist(movieById);여러 예시 업데이트
다음 예시 일치하는 문서의 title 값을 "The Three Stooges" 에서 "The 3 Stooges"로 업데이트합니다. 그런 다음 executeUpdate() 메서드를 예시 하여 데이터베이스 에 변경 사항을 적용 .
var updateResult = session.createMutationQuery( "update Movie set title = :new where title = :old") .setParameter("new", "The 3 Stooges") .setParameter("old", "The Three Stooges") .executeUpdate();System.out.println("Number of movies updated: " + updateResult);var updateResult = entityManager.createQuery( "update Movie m set m.title = :new where m.title = :old") .setParameter("new", "The 3 Stooges") .setParameter("old", "The Three Stooges") .executeUpdate();System.out.println("Number of movies updated: " + updateResult);대량 업데이트 성명서의 SET 절은 리터럴 값 대신 표현식을 사용할 수도 있습니다. 표현식은 업데이트되는 필드 또는 엔터티의 다른 필드를 참조할 수 있습니다.
다음 예시는 산술 표현식을 사용하여 title 값이 "The 3 Stooges"인 문서의 year 값을 증가시킵니다.
var updateResult = session.createMutationQuery( "update Movie m set m.year = m.year + 1 where m.title = :title") .setParameter("title", "The 3 Stooges") .executeUpdate();System.out.println("Number of movies updated: " + updateResult);다음 예시에서는 필드 참조를 사용하여 year 값이 1920인 문서의 plot 값을 title 값과 일치하도록 설정합니다.
var updateResult = session.createMutationQuery( "update Movie m set m.plot = m.title where m.year = :year") .setParameter("year", 1920) .executeUpdate();System.out.println("Number of movies updated: " + updateResult);조건부 논리에 기반한 다중 업데이트 예시
다음 예시는 CASE 표현식을 사용하여 각 문서의 year 값이 2000년 이후인지 여부에 따라 plot 값을 설정합니다. Hibernate ORM 확장은 CASE 표현식을 MongoDB $switch 연산자로 변환하고 $set 파이프라인 단계를 사용하여 업데이트를 적용합니다.
var updateResult = session.createMutationQuery( "update Movie m set m.plot = case when m.year > 2000 then 'Modern release' " + "else 'Classic release' end where m.title = :title") .setParameter("title", "The 3 Stooges") .executeUpdate();System.out.println("Number of movies updated: " + updateResult);CASE 표현식에 대해 자세히 알아보려면 쿼리 지정 가이드의 조건부 논리에 대한 사용 사례 표현식 섹션을 참조하세요.
문서 업서트
업서트 작업은 일치하는 문서가 있으면 문서를 업데이트하고, 일치하는 문서가 없으면 새 문서를 삽입합니다. 업서트를 수행하려면 upsert() 또는 upsertMultiple() 메서드를 사용합니다. 이러한 메서드는 Hibernate의 StatelessSession API에서만 사용할 수 있습니다.
참고
StatelessSession 인스턴스는 조회한 엔터티의 변경 사항을 추적하지 않습니다. 엔터티에 대한 변경 사항을 저장하려면 다른 쓰기 (write) 메서드에 전달하세요. 대량 쓰기 (write) 워크플로에는 StatelessSession을(를) 사용하세요.
엔티티 요구 사항
Hibernate ORM 확장은 엔티티의 식별자에서 업서트 작업에 대한 필터를 생성하므로, upsert()을(를) 호출하기 전에 애플리케이션에서 식별자 값을 할당해야 합니다.
upsert() 메서드는 엔티티가 @ObjectIdGenerator 주석을 사용하더라도 식별자 값을 생성하지 않습니다. 식별자 값을 할당하지 않으면 Hibernate ORM 확장이 null _id 값으로 문서를 저장합니다.
@Column(updatable = false) 어노테이션을 사용하여 업서트 작업 중에 필드가 업데이트되지 않도록 보호할 수 있습니다. 다음 Movie 엔터티 정의는 released 필드에 @Column(updatable = false)을(를) 주석으로 추가합니다. 이는 Hibernate ORM 확장 프로그램에 문서를 삽입할 때는 필드에 쓰기 (write)를 수행하고 기존 문서를 업데이트할 때는 필드를 생략하도록 지시합니다.
@Entity@Table(name = "movies")public class Movie { @Id @ObjectIdGenerator private ObjectId id;
private String title; private int year;
@Column(updatable = false) private Instant released;
// Getters and setters omitted}Hibernate ORM 확장은 생성된 업데이트 성명서의 $set 연산자에서 삽입 가능하고 업데이트 가능한 필드를 전송합니다. 이는 $setOnInsert 연산자에서 @Column(updatable = false)로 주석된 필드와 같은 삽입 가능 필드만 전송합니다.
업서트 원 예시
다음 예시는 Movie 엔터티 인스턴스를 생성하고 이를 upsert() 메서드에 전달합니다. 지정된 ObjectId 값을 가진 문서가 있으면 Hibernate ORM 확장이 해당 문서의 title 및 year 값을 업데이트합니다. 그렇지 않으면 Hibernate ORM 확장이 새 문서를 삽입합니다.
try (StatelessSession statelessSession = sf.openStatelessSession()) { var movie = new Movie(); movie.setId(new ObjectId("573a1398f29313caabce9682")); movie.setTitle("The General"); movie.setYear(1926); movie.setReleased(Instant.parse("1927-02-24T00:00:00Z"));
statelessSession.upsert(movie);}다중 업서트 예시
한 번의 작업으로 여러 엔티티 인스턴스를 업서트하려면 upsertMultiple() 메서드에 인스턴스 목록을 전달하세요. 다음 예시는 두 개의 Movie 엔티티 인스턴스를 업서트합니다.
try (StatelessSession statelessSession = sf.openStatelessSession()) { var firstMovie = new Movie(); firstMovie.setId(new ObjectId("573a1398f29313caabce9682")); firstMovie.setTitle("The General"); firstMovie.setYear(1926);
var secondMovie = new Movie(); secondMovie.setId(new ObjectId("573a1398f29313caabce9683")); secondMovie.setTitle("Metropolis"); secondMovie.setYear(1927);
statelessSession.upsertMultiple(List.of(firstMovie, secondMovie));}업서트 제한 사항
다음 객체 매핑은 업서트 작업에서 지원되지 않습니다. 이러한 매핑 중 하나를 사용하는 엔티티를 업서트할 때 Hibernate ORM 확장은 FeatureNotSupportedException을(를) 발생시킵니다:
@Version주석이 달린 필드가 있는 엔터티입니다.@Column(insertable = false)주석이 달린 필드가 있는 엔터티입니다. MongoDB 쿼리 언어는 작업이 기존 문서와 일치할 때만 필드를 쓰기 (write)할 수 있는 방법을 제공하지 않습니다.식별자만이 유일한 영구 속성인 엔터티입니다. 이러한 유형의 엔터티에 대한 업서트는 업데이트할 필드가 없으므로 Hibernate ORM 확장이 작업을 거부합니다.
문서 삭제
다음 작업을 수행하여 컬렉션 에서 문서를 삭제 수 있습니다.
문서 하나 삭제: 세션 또는 엔터티 관리자에서
remove()메서드를 호출하여 삭제 하려는 엔터티 인스턴스 인수로 전달합니다.여러 문서 삭제: 세션 또는 엔티티 관리자의
createQuery()또는createMutationQuery()메서드에 삭제 성명서 전달합니다. 그런 다음executeUpdate()메서드를 호출하여 데이터베이스 에 변경 사항을 적용 .
팁
최대 절전 모드 ORM을 사용하여 데이터를 삭제하는 방법에 대해 자세히 학습 다음 리소스를 참조하세요.
하나의 예시 삭제
다음 예시 ObjectId 값으로 문서 조회합니다. 그런 다음 이 예시 에서는 세션에서 remove() 메서드를 호출하여 sample_mflix.movies 컬렉션 에서 해당 문서 삭제 .
// Your ObjectId value might differMovie movieToDelete = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));session.remove(movieToDelete);// Your ObjectId value might differMovie movieToDelete = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));entityManager.remove(movieToDelete);여러 예시 삭제
다음 예시 year 값이 1920 인 모든 문서를 sample_mflix.movies 컬렉션 에서 삭제합니다. 이 예시 삭제 성명서 createMutationQuery() 메서드에 전달한 다음 executeUpdate() 메서드를 호출하여 데이터베이스 에 변경 사항을 적용 .
var deleteResult = session.createMutationQuery( "delete Movie where year = :y") .setParameter("y", 1920) .executeUpdate();System.out.println("Number of movies deleted: " + deleteResult);var deleteResult = entityManager.createQuery( "delete Movie m where m.year = :y") .setParameter("y", 1920) .executeUpdate();System.out.println("Number of movies deleted: " + deleteResult);추가 정보
최대 절전 모드 ORM을 사용하여 CRUD 작업을 수행하는 방법에 대해 자세히 학습 다음 리소스를 참조하세요.
하이버네이트 ORM 사용자 가이드 의 지속성 컨텍스트
만들기, 읽기, 업데이트 및 삭제 예시를 더 보려면 시작하기 튜토리얼의 다음 섹션을 참조하세요.
최대 절전 모드 ORM 확장을 사용하여 쿼리를 실행 방법에 대해 자세히 학습 다음 가이드를 참조하세요.