개요
이 가이드에서는 Hibernate ORM용 MongoDB 확장을 사용하여 MongoDB 데이터베이스에서 네이티브 쿼리를 실행하는 방법을 학습할 수 있습니다. HQL(Hibernate 쿼리 언어) 또는 JPQL(Jakarta Persistence 쿼리 언어) 대신 네이티브 쿼리를 사용하면 MQL(MongoDB 쿼리 언어)을 사용하여 쿼리를 지정할 수 있습니다. MQL은 MongoDB 문서 기반 모델과 상호 작용하도록 설계된 쿼리 구문입니다.
최대 절전 모드 ORM의 createQuery() 메서드는 일부 MongoDB 쿼리 기능을 지원 하지 않습니다. createNativeQuery() 메서드를 사용하면 MQL 에서 데이터베이스 쿼리를 지정하고 하이버네이트 ORM 확장의 일부 운영 제한 사항을 우회할 수 있습니다.
확장된 쿼리 기능을 위해 MongoClient 객체 에서 직접 쿼리를 실행 수도 있습니다.
샘플 데이터
이 가이드 의 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix.movies 컬렉션 나타내는 Movie 엔터티를 사용합니다. Movie 엔터티의 정의는 다음과 같습니다.
import com.mongodb.hibernate.annotations.ObjectIdGenerator;import org.bson.types.ObjectId;import java.util.List;
import jakarta.persistence.Entity;import jakarta.persistence.Id;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 int runtime; private List<String> cast; private List<String> directors;
public Movie(String title, String plot, int year, int runtime, List<String> cast, List<String> directors) { this.title = title; this.plot = plot; this.year = year; this.runtime = runtime; this.cast = cast; this.directors = directors; }
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 int getRuntime() { return runtime; }
public void setRuntime(int runtime) { this.runtime = runtime; }
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; }}최대 절전 모드용 MongoDB 확장 ORM을 사용하여 이 MongoDB 샘플 컬렉션과 상호 작용하는 Java 애플리케이션 만드는 방법을 학습하려면 시작하기 튜토리얼을 참조하세요.
네이티브 쿼리 실행
네이티브 MongoDB 쿼리 실행 하려면 집계 파이프라인 에서 컬렉션 할 쿼리 과 쿼리 기준을 포함하는 MQL ( MongoDB Query Language) 성명서 지정합니다.
MQL 성명서 형식은 다음과 같습니다.
String mqlSyntax = """{ aggregate: "<collection to query>", pipeline: [ <aggregation pipeline stages> ]}""";중요
$ 프로젝트 단계 요구 사항
MQL 성명서의 집계 파이프라인에는 $project 단계가 포함되어야 합니다. 쿼리 문서를 엔티티 인스턴스로 반환하려면 _id 필드를 포함하여 $project 단계에서 각 엔티티 필드를 지정해야 합니다. Hibernate ORM 확장은 프로젝트하는 필드를 반환하고 생략할 경우 _id을(를) 억제합니다. _id을(를) 생략하는 엔티티 바인딩 쿼리는 엔티티 식별자가 _id(으)로 매핑되기 때문에 Unknown column label [_id] (으)로 실패할 수 있습니다. 식별자를 계속 사용할 수 있도록 하려면 _id: 1을(를) 프로젝트하세요.
그 다음에 MQL 문을 createNativeQuery() 메서드에 전달합니다.
네이티브 쿼리를 사용하여 다음 작업을 수행할 수 있습니다.
중요
확장 JSON 구문 필요
네이티브 쿼리는 Extended JSON v2 형식으로 쓰기 (write)해야 합니다. Hibernate ORM 확장은 네이티브 쿼리에서 작은따옴표나 MongoDB Server shell 정규 표현식 구문(/pattern/)을 지원하지 않습니다. 예를 들어, 정규 표현식으로 쿼리하려면 /pattern/ 대신 $regularExpression Extended JSON 유형을 사용하세요.
문서 필터 및 정렬
이 예시 createNativeQuery() 메서드에 MQL 성명서 전달하여 sample_mflix.movies 컬렉션 에 대한 네이티브 쿼리 실행합니다. 이 코드는 다음 집계 파이프라인 단계 지정합니다.
$match: 제목 필드 값이 다음과 같은 문서를 필터링합니다."The Parent Trap"$sort: 일치하는 문서를year필드를 기준으로 내림차순으로 정렬합니다.$project:Movie엔터티에 정의된 각 문서 필드 반환합니다.
String nativeQuery = """{ aggregate: "movies", pipeline: [ { $match: { title: { $eq: "The Parent Trap" } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ]}""";
var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList();
for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());}산술 연산자 사용
참고
네이티브 쿼리는 Hibernate ORM 확장 기능에서 지원하지 않는 산술 작업에 가장 적합합니다. Hibernate ORM 확장 기능이 지원하는 산술 연산자에 대한 자세한 내용은 기능 호환성 페이지의 쿼리 지원 섹션을 참조하세요.
다음 예시 sample_mflix.movies 컬렉션 에서 다음 조치를 수행하는 네이티브 쿼리 실행합니다.
year값이2000보다 크고runtime필드 존재하는 문서와 일치하는$match단계를 지정합니다.runtimeHours이라는 새 필드 추가하는$addFields단계를 지정합니다.$divide산술 연산자 사용하여 새runtimeHours필드 의runtime값을 분에서 시간으로 변환합니다._id필드를 포함하여Movie엔터티에 정의된 각 문서 필드를 반환하는$project단계를 지정합니다.업데이트된 각 문서 의
title값을 출력합니다.
String nativeQuery = """{ aggregate: "movies", pipeline: [ { $match: { year: { $gt: 2000 }, runtime: { $exists: true } } }, { $addFields: { runtimeHours: { $divide: [ "$runtime", 60 ] } }}, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1, runtimeHours: 1 }} ]}""";
var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList();
for (Movie result : results) { System.out.println("Added field to movie: " + result.getTitle());}MongoDB 검색 쿼리 실행
네이티브 쿼리를 실행 데이터베이스 에서 데이터에 대한 세분화된 텍스트 검색인 MongoDB Search 쿼리를 수행할 수 있습니다. 이러한 쿼리는 텍스트 구문 일치, 관련성에 대한 결과 채점, 일치 항목 강조 표시 등의 고급 검색 기능을 제공합니다.
중요
트랜잭션 내에서는 MongoDB Search 쿼리 실행 수 없습니다.
검색 쿼리 지정하려면 쿼리 하려는 필드를 포함하는 검색 인덱스 만듭니다. 그런 다음 $search 또는 $searchMeta 단계가 포함된 createNativeQuery() 메서드에 집계 파이프라인 전달합니다.
팁
MongoDB Search
MongoDB Search 검색 쿼리 및 인덱스에 대해 자세히 학습하려면 MongoDB Server 매뉴얼의 MongoDB Search 개요 를 참조하세요.
이 예시 $search 파이프라인 단계를 createNativeQuery() 메서드에 전달하여 검색 쿼리 실행합니다. 이 코드는 다음 조치를 수행합니다.
plot필드 포함하는 검색 인덱스 지정합니다.<indexName>자리 표시자를 검색 인덱스 이름으로 바꿔야 합니다.plot값 사이에3단어 이하의"whirlwind romance"문자열이 포함된 문서를 쿼리합니다._id필드를 포함하여Movie엔터티에 정의된 각 문서 필드를 반환하는$project단계를 지정합니다.일치하는 문서의
title및plot값을 출력합니다.
String nativeQuery = """{ aggregate: "movies", pipeline: [ { $search: { index: "<indexName>", phrase: { path: "plot", query: "whirlwind romance", slop: 3 } } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ]}""";
var results = session.createNativeQuery(nativeQuery, Movie.class) .getResultList();
for (Movie result : results) { System.out.println("Title: " + result.getTitle() + ", Plot: " + result.getPlot());}네이티브 쿼리에서 매개변수 사용
MQL 성명서에서 값을 지정하기 위해 이름 지정 매개변수(:name) 또는 순서 매개변수(?1)를 사용할 수 있습니다. 다음 예시는 title 매개변수 값을 명명 또는 서순 매개변수로 접과하고 setParameter()으로 매개변수 값을 제공하는 방법을 보여줍니다.
String nativeQuery = """{ aggregate: "movies", pipeline: [ { $match: { title: { $eq: :movieTitle } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ]}""";
var results = session.createNativeQuery(nativeQuery, Movie.class) .setParameter("movieTitle", "The Parent Trap") .getResultList();
for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());}String nativeQuery = """{ aggregate: "movies", pipeline: [ { $match: { title: { $eq: ?1 } } }, { $sort: { year: -1 } }, { $project: { _id: 1, title: 1, plot: 1, year: 1, runtime: 1, cast: 1 } } ]}""";
var results = session.createNativeQuery(nativeQuery, Movie.class) .setParameter(1, "The Parent Trap") .getResultList();
for (Movie movie : results) { System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());}MongoClient 작업 실행
createQuery() 메서드와 createNativeQuery() 메서드가 모두 지원하지 않는 데이터베이스 작업을 실행 하려는 경우 Java 애플리케이션 에서 직접 MongoClient 객체 에 대해 작업할 수 있습니다. MongoClient으로 작업할 때 MongoDB Java Sync Driver의 기능에 액세스 할 수 있습니다.
Java 운전자 사용하여 MongoDB 와 상호 작용 하는 방법을 학습 MongoDB Java 드라이버 설명서를 참조하세요.
MongoClient로 인덱스 생성
하이버네이트 ORM 확장을 사용하여 컬렉션 에 인덱스를 생성할 수는 없지만 MongoClient 를 인스턴스화하고 Java 드라이버의 createIndex() 메서드를 사용할 수 있습니다. 다음 코드는 sample_mflix.movies 컬렉션 에 title 필드 인덱스 생성합니다.
// Replace the <connection URI> placeholder with your MongoDB connection URIString uri = "<connection URI>";MongoClient mongoClient = MongoClients.create(uri);MongoDatabase db = mongoClient.getDatabase("sample_mflix");MongoCollection<Document> collection = db.getCollection("movies");
String indexResult = collection.createIndex(Indexes.ascending("title"));System.out.println(String.format("Index created: %s", indexResult));Java 운전자 사용하여 인덱스를 생성하는 방법에 대해 자세히 학습하려면 Java 운전자 설명서의 인덱스 가이드를 참조하세요.
추가 정보
이 가이드 에서 설명하는 쿼리 언어에 대해 자세히 학습 다음 리소스를 참조하세요.