왜 Scala와 같은 기능적 언어로 된 ORM이 필요하지 않습니까? 기능 언어의 힘이있을 때 객체에

Spring + Hibernate 프로젝트에서 Java에서 Scala로 전환하여 패턴 일치, 옵션 및 일반적인 구문과 같은 일부 Scala 기능을 활용할 수 있는지 궁금합니다. 나는 Scala 생태계에서 기본적으로 ORM을 찾고 있었고 Activate와 같은 생각을 발견했습니다 (그러나 대부분 Hibernate를 Scala와 함께 사용할 수 있는지 찾으려고 노력합니다). 이것을 찾고 JPA + Scala에 관한 Play 문서 에서 이것을 읽었습니다 .

그러나 가장 중요한 점은 기능 언어의 힘이있을 때 객체에 대한 관계형 맵퍼가 실제로 필요합니까?
아마 아닙니다. JPA는 데이터 변환에서 Java의 부족한 기능을 추상화하는 편리한 방법이지만 Scala에서 Java를 사용하기 시작하면 실제로 잘못된 느낌이 듭니다.

함수형 프로그래밍을 사용하여 완전한 응용 프로그램을 만드는 방법에 대한 깊은 이해가 없기 때문에 (OO + Functional을 결합하기 때문에 점진적으로 이해할 수 있도록 Scala를 사용하려는 이유), 이해할 수 없습니다. 기능 언어가있는 ORM이 필요하지 않은 이유와 도메인 모델의 지속성을 다루는 기능적 접근 방법은 무엇입니까?

비즈니스 로직에 대한 DDD 접근 방식은 여전히 ​​Scala와 관련이 있습니다.



답변

이와 같이 논의 할 때마다 중요한 것은 객체 관계 맵퍼 ( “ORM”)와 데이터베이스 추상화 계층 을 명확하게 구분하는 것 입니다. ORM은 일종의 데이터베이스 추상화 계층이지만 모든 데이터베이스 추상화 계층이 ORM 인 것은 아닙니다. 이것을 이해하기 위해 공부하는 좋은 도구 중 하나는 파이썬의 인기있는 SQLAlchemy 라이브러리입니다.이 라이브러리는 “SQL 툴킷 Object Relational Mapper”(내 볼드체)로 다른 것으로 생각합니다. 주요 기능 페이지 에 넣을 때 :

ORM이 필요하지 않습니다

SQLAlchemy는 Core ORM . Core 자체는 완전한 기능을 갖춘 SQL 추상화 툴킷으로, 다양한 DBAPI 구현 및 동작에 대한 매끄러운 추상화 계층을 제공하며 생성 된 Python 표현식을 통해 SQL 언어를 표현할 수있는 SQL Expression Language도 제공합니다. DDL 문을 생성하고 기존 스키마를 검사 할 수있는 스키마 표현 시스템과 파이썬 유형을 데이터베이스 유형에 매핑 할 수있는 유형 시스템은 시스템을 반올림합니다. 그러면 Object Relational Mapper는 Core를 기반으로하는 선택적 패키지입니다.

프론트 페이지는 다음과 같이 ORM을 설명합니다.

SQLAlchemy는 데이터 맵퍼 패턴을 제공하는 선택적 구성 요소 인 ORM (Object-Relational Mapper)으로 가장 유명합니다. 여기서 클래스는 개방형으로 여러 가지 방법으로 데이터베이스에 맵핑 할 수 있습니다. 처음부터 깨끗하게 분리되었습니다.

ORM의 핵심 아이디어는 유명한 객체 관계형 임피던스 불일치 를 시도하고 연결하는 것 입니다. 이는 사용자 정의 클래스 와 데이터베이스 스키마의 테이블 간 관계를 정의 하고 애플리케이션 클래스에 대한 자동 “저장”및 “로드”조작을 제공함을 의미합니다.

반대로, 비 ORM 데이터베이스 추상화 계층은 관계 지향 데이터 모델과 SQL에 더 헌신적 인 경향이 있으며, 객체 지향에는 전혀 영향을 미치지 않습니다. 따라서 테이블과 클래스 사이에 “매핑 (mapping)”기능을 제공하고 프로그래머로부터 데이터베이스 스키마를 숨기는 대신 데이터베이스를 프로그래머 에게 노출 시키는 경향이 있지만 API와 추상화는 더 좋습니다. 예를 들어, SQL 쿼리 빌더를 사용하면 다음과 같이 문자열 조작없이 프로그래밍 방식으로 복잡한 SQL 쿼리를 생성 할 수 있습니다 ( Java 용 jOOQ 라이브러리의 예 ).

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

지금, Play 프레임 워크는 방금 설명한 것과 100 % 리그가 아닌 것처럼 보이지만 그 논쟁은이 일반적인 공간에있는 것처럼 보입니다. 관계형 모델을 클래스로 변환하고 다시 변환하는 대신 직접 작업하십시오.

jOOQ 라이브러리 으로 ORMs에 대위법으로 연구 가치가있다. 또한 읽을 가치가있는 관련 블로그 항목이 있습니다.


답변

함수형 프로그래밍을 많이 할 때까지 설명하기가 어렵습니다. 객체 지향 프로그래밍에서 데이터는 하나의 객체에 갇혀 있고 그대로 유지됩니다. 그 객체는 조금씩 전달되어 약간 수정되었지만 일반적으로 해당 데이터의 수명 동안 동일한 “동일성”으로 기본적으로 작업하고 있습니다.

ORM은 일반적으로 해당 패러다임을 중심으로 설계되었습니다. 데이터베이스에서 일부 데이터를 검색하여 객체로 병합하고 잠재적으로 데이터를 한꺼번에 수정하면 완료된 후에도 데이터베이스에 다시 쓸 수있는 동일한 객체가 있습니다.

함수형 프로그래밍은 다르게 작동합니다. 데이터는 수명 기간 동안 단일 ID를 유지하지 않습니다. 분할, 복사, 공유 및 변환됩니다. 그것은 많은 기능을 통해 흐르고 결국 필요한 출력 형태로 다시 어셈블됩니다. 모든 데이터베이스 API가 기능적 언어로 자연스럽게 느껴지려면이를 고려해야하고 JPA는 그렇지 않습니다.


답변

scala에서는 데이터베이스 테이블을 객체에 매핑하는 것이 여전히 유용하며이를 수행하는 몇 가지 방법이 있습니다.

스칼라 세계에서 인기있는 프레임 워크는 매끈하다 . ORM이 아니기 때문에 (즉, 명시 적으로 조인하도록 지시하지 않고 관계를 페치하지 않음) ORM이 아닙니다.

따라서 여전히 객체를 데이터베이스 행에 매핑하지만 객체는 변경할 수 없으므로 상태 플러싱이 없으며 모나드 DSL을 사용하여 명시 적으로 쿼리를 실행합니다. 결과적으로 변경 가능성과 예측할 수없는 N + 1 문제없이 ORM의 “좋은”부분을 많이 얻을 수 있습니다.

사람들은 anorm 과 같이 훨씬 얇은 라이브러리를 사용하여 큰 성공을 거두었 습니다. 코드를 아름답게 유지하기 위해 기능적 기술을 사용하여 또는 straight JDBC .

JDBC 위에 기능 기술을 적용하는 환상적인 라이브러리 중 하나는 doobie 입니다.

따라서 데이터베이스 액세스에 대한 많은 선택 사항이 있지만 실제로는 ORM으로 보이는 최대 절전 모드가 변경 가능성에 대한 편향으로 인해 최고의 선택이 아닙니다.


답변

객체 지향 언어에서도 ORM이 필요하지 않습니다.

먼저 누가 데이터를 영구 저장소에서 개체로 실제로 복사해야한다고 말했습니까? 스몰 토크 뒤에있는 앨런 케이 (Alan Kay )는 객체가 데이터를 제거하기를 원했다 . 그는 객체가 데이터가 저장된 일부 영역에 대한 참조 만 가질 수 있다고 제안했습니다.

둘째-그것을 달성하는 가장 좋은 방법은 무엇입니까? 나는 자신의 책임으로 객체를 식별 하고 소유 한 데이터에 대해서는 생각하지 않는 것이 좋습니다 . CRC 카드 접근에 대해 들었다면 정확히 사용됩니다.

마지막으로 OO 필드로 돌아갈 경우를 대비 하여 구현 방법이 있습니다 .