programing

휴지 상태에 인수 생성자가 필요하지 않은 이유는 무엇입니까?

shortcode 2022. 9. 25. 15:34
반응형

휴지 상태에 인수 생성자가 필요하지 않은 이유는 무엇입니까?

인수 없는 생성자는 필수 조건입니다(Hibernate와 같은 도구는 이 생성자에 대한 반사를 사용하여 개체를 인스턴스화합니다).

이 흔해빠진 답변을 받았는데 누가 더 설명해 줄 수 있나요?감사합니다.

최대 절전 모드 및 일반적으로 반사를 통해 개체를 만드는 코드를 사용하여 클래스의 새 인스턴스를 만듭니다.이 메서드를 사용하려면 퍼블릭 no-arg 컨스트럭터가 개체를 인스턴스화할 수 있어야 합니다.대부분의 경우 arg가 없는 컨스트럭터를 제공하는 것은 문제가 되지 않습니다.

시리얼라이제이션에서는 생성자를 호출하지 않고 jvm 매직으로 객체를 생성하기 때문에 no-arg 컨스트럭터가 없는 것을 회피할 수 있는 serialization 기반의 hack이 있습니다.그러나 이 기능을 모든 VM에서 사용할 수 있는 것은 아닙니다.예를 들어 XStream에서는 퍼블릭 no-arg 컨스트럭터가 없는 개체의 인스턴스를 생성할 수 있지만 특정 VM에서만 사용할 수 있는 소위 "확장" 모드로 실행해야 합니다(자세한 내용은 링크를 참조하십시오).Hibernate의 설계자는 확실히 모든 VM과의 호환성을 유지하기로 선택했기 때문에 이러한 트릭을 피하고 공식적으로 지원되는 리플렉션 방법을 사용합니다.Class<T>.newInstance()무료 컨스트럭터가 필요합니다.

음, 모두 죄송합니다. 하지만 Hibernate를 사용하려면 클래스에 매개 변수가 없는 생성자가 있어야 합니다.JPA 2.0 사양에서는 이것이 필요하며, 이것은 JPA에 비해 매우 어설프다.JAXB와 같은 다른 프레임워크도 그것을 필요로 합니다.이것 또한 이러한 프레임워크에 대해서는 매우 어설프게 느껴집니다.

(실제로 JAXB는 엔티티 공장을 허용한다고 생각되지만, 이러한 공장 자체를 인스턴스화해, 파라미터가 없는 건설업자를 가질 것을 요구하고 있습니다.이것은 제 책에 의하면 공장을 허가하지 않는 것과 다름없는 것입니다.그것은 얼마나 어설픈 일입니까!)

하지만 동면기에는 그런 것이 필요하지 않다.

휴지 상태에서는 필요한 생성자 매개 변수를 사용하여 개체를 인스턴스화할 수 있는 인터셉터 메커니즘(설명서의 "인터셉터" 참조)을 지원합니다.

기본적으로는 휴지 상태를 설정할 때 Hiberney를 구현하고 있는 객체를 전달합니다.org.hibernate.Interceptor그 후, 최대 절전 모드로 전환됩니다.instantiate()오브젝트의 새로운 인스턴스가 필요할 때마다 그 인터페이스의 메서드를 사용하여 그 메서드를 구현하면new원하는 방식으로 물건을 만들 수 있습니다.

나는 한 프로젝트에서 그것을 해 본 적이 있는데 그것은 아주 잘 작동한다.이 프로젝트에서는 가능한 한 JPA를 통해 작업을 수행하고 있으며, 다른 옵션이 없을 때만 인터셉터와 같은 휴지 상태 기능을 사용합니다.

시작 시 엔티티 클래스별로 정보 메시지를 발행하여 Hibernate는 이에 대해 다소 불안한 것 같습니다.INFO: HHH000182: No default (no-argument) constructor for class그리고.class must be instantiated by Interceptor나중에 인터셉터로 인스턴스화하면 만족합니다.

Hibernate 이외의 툴에 대한 질문의 "Why" 부분에 대한 답변은 "절대 타당한 이유가 없기 때문"이며, 이는 Hibernate 인터셉터의 존재로 증명됩니다.클라이언트 오브젝트의 인스턴스화를 위한 유사한 메커니즘을 지원할 수 있는 툴이 많이 있지만 지원되지 않기 때문에 오브젝트를 직접 작성하기 때문에 파라미터가 필요 없는 컨스트럭터가 필요합니다.이러한 툴의 개발자가, 무식한 애플리케이션·프로그래머가 사용하는, 마법으로 가득 찬 프레임워크를 작성하는 닌자·시스템·프로그래머라고 생각하기 때문에, 이러한 일이 일어나고 있다고 믿고 싶다.팩토리 패턴. (좋아, 나도 그렇게 생각하고 싶어. 그렇게 생각하지 않아.농담입니다.)

휴지상태는 객체를 인스턴스화합니다.그래서 그들을 인스턴스화할 수 있어야 합니다.no-arg 컨스트럭터가 없으면 Hibernate는 어떤 인수를 전달해야 하는지 알 수 없습니다.

휴지 상태 문서에는 다음과 같이 기재되어 있습니다.

4.1.1 논거가 없는 생성자 구현

모든 영속 클래스에는 기본 컨스트럭터(비공개 클래스일 수 있음)가 있어야 합니다.이것에 의해, 휴지 상태에서는, 다음의 방법으로 클래스가 인스턴스화할 수 있습니다.Constructor.newInstance()Hibernate에서 런타임 프록시를 생성하기 위해 패키지 가시성 이상의 기본 컨스트럭터를 사용하는 것이 좋습니다.

휴지 상태는 필드 또는 속성 액세스 전략을 지원하는 ORM 프레임워크입니다.단, 다음과 같은 문제로 인해 컨스트럭터 기반 매핑은 지원되지 않습니다.

1 ① 클래스에 컨스트럭터가 많이 포함되어 있으면 어떻게 됩니까?

public class Person {

    private String name;
    private Integer age;

    public Person(String name, Integer age) { ... }
    public Person(String name) { ... }
    public Person(Integer age) { ... }

}

보시는 바와 같이 Hibernate는 어떤 컨스트럭터를 호출해야 하는지 예측할 수 없기 때문에 불일치 문제에 대처합니다.예를 들어 저장된 Person 개체를 검색해야 한다고 가정합니다.

Person person = (Person) session.get(Person.class, <IDENTIFIER>);

Person 개체를 검색하기 위해 호출을 휴지 상태로 만들어야 하는 생성자를 볼 수 있습니까?

2 † 마지막으로 리플렉션을 사용하여 휴지 상태에서는 no arg 컨스트럭터를 통해 클래스를 인스턴스화할 수 있습니다.그래서 당신이 전화했을 때

Person person = (Person) session.get(Person.class, <IDENTIFIER>);

휴지 상태에서는 다음과 같이 사용자 개체를 인스턴스화합니다.

Person.class.newInstance();

API 설명서에 따르면

인수 목록이 비어 있는 식에 의해 클래스가 인스턴스화됩니다.

이야기의 교훈

Person.class.newInstance();

와 유사합니다.

new Person();

다른 것은 없어요

휴지 상태에서는 쿼리의 결과(반사를 통해) 인스턴스를 생성해야 합니다. 휴지 상태에서는 엔티티의 no-arg 컨스트럭터에 의존하므로 no-arg 컨스트럭터를 제공해야 합니다.무엇이 명확하지 않은가?

실제로 0-args 생성자가 없는 클래스를 인스턴스화할 수 있습니다. 클래스의 생성자 목록을 가져오고 하나를 선택한 다음 가짜 매개 변수를 사용하여 호출할 수 있습니다.

이것이 가능하고, 저는 이것이 효과가 있고 문제가 되지 않을 것이라고 생각하지만, 여러분은 그것이 매우 이상하다는 것에 동의해야 할 것입니다.

Hibernate와 같이 오브젝트 구성(아마도 0-arg 컨스트럭터를 호출하여 Reflection을 통해 인스턴스의 필드를 직접 수정하는 것 같습니다.setters)를 호출하는 방법을 알고 있는 것 같습니다.새로운 오브젝트가 원하는 오브젝트가 되도록 적절한 파라미터를 사용하여 컨스트럭터를 호출합니다.오브젝트를 인스턴스화한 후 뮤트하는 것은 다소 '반자바'(또는 반순수 이론 자바)라고 생각합니다.직접 필드 조작을 통해 이것을 실시하면 캡슐화 및 고급 캡슐화 같은 것이 됩니다.

적절한 방법은 hibernate 매핑에서 적절한 생성자를 사용하여 데이터베이스 행의 정보에서 개체를 인스턴스화하는 방법을 정의하는 것입니다.하지만 이건 더 복잡해 즉, 두 동면기가 더 복잡해지고 지도 제작도 더 복잡해질 거야이 모든 것이 보다 「순수」해지기 위해서입니다만, 현재의 어프로치보다 유리하다고는 생각하지 않습니다( 「적절한 방법」에 대해 만족하는 것 이외에는).

그렇지만, 하이버네이트의 어프로치가 매우 「깨끗」한 것은 아니기 때문에, 0-arg의 컨스트럭터를 가지는 것은 엄밀하게는 필요 없습니다만, 그 전에 「적절한」(합리적인 이유라고는 해도)을 크게 빗나갔을 때는, 순수하게 「적절한」의 근거에 근거해 실시했다고 생각합니다만, 그 요건을 어느 정도 이해할 수 있습니다.

이름/이름 충돌 변경, 생성자 내부의 정의되지 않은 논리, o의 속성과 일치하지 않는 매개 변수화된 생성자의 임의 매개 변수와 데이터를 일치시키려고 시도하는 것보다 리플렉션을 통해 매개 변수 없는 생성자를 사용하여 개체를 만들고 그 속성을 데이터로 채우는 것이 훨씬 쉽습니다.bject 등

리플렉션을 통한 매개 변수화된 생성자는 매우 취약하며, 매개 변수 없는 생성자는 응용 프로그램의 안정성과 개발자의 객체 동작 제어를 모두 제공하기 때문에 많은 ORM 및 직렬화에는 매개 변수 없는 생성자가 필요합니다.

휴지 상태는 느린 로드에 프록시를 사용합니다.생성자를 정의하지 않거나 비공개로 설정해도 프록시 메커니즘에 의존하지 않는 몇 가지 작업이 계속 작동할 수 있습니다.예를 들어, 쿼리 API를 사용하여 오브젝트를 직접 로드(생성자 없음)하는 경우.

단, session.load method()를 사용하면 인스턴스화가 발생합니다.생성자를 사용할 수 없으므로 프록시 생성기 lib에서 예외가 발생했습니다.

이 남자도 비슷한 상황을 보고했어요

http://kristian-domagala.blogspot.com/2008/10/proxy-instantiation-problem-from.html

스태틱 내부 클래스와 스태틱하지 않은 내부 클래스의 차이를 설명하는 Java 언어 사양의 다음 섹션을 참조하십시오.http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3

스태틱 내부 클래스는 개념적으로 .java 파일로 선언된 일반 일반 클래스와 다르지 않습니다.

휴지 상태에서는 프로젝트를 인스턴스화해야 하기 때문에프로젝트 인스턴스, 프로젝트와는 독립적으로 PK 실행PK는 정적 내부 클래스이거나 자체 .java 파일로 선언되어야 합니다.

org.internate를 참조합니다.인스턴스화예외: 기본 생성자 없음

In my case, I had to hide my no-arg constructor, but because Hibernate I couldn't do it. So I solved the problem in another way.

/**
 * @deprecated (Hibernate's exclusive constructor)
 */
public ObjectConstructor (){ }

Summarizing of what is below. It matters if you want to be JPA compatible or strictly Hibernate

Just look at official documentation: https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo

Section 2.1 The Entity Class of the JPA 2.1 specification defines its requirements for an entity class. Applications that wish to remain portable across JPA providers should adhere to these requirements:

One point says:

The entity class must have a public or protected no-argument constructor. It may define additional constructors as well.

However, hibernate is less strict in this:

Hibernate, however, is not as strict in its requirements. The differences from the list above include:

One point says:

The entity class must have a no-argument constructor, which may be public, protected or package visibility. It may define additional constructors as well.

More on that is right below: https://docs.jboss.org/hibernate/orm/5.6/userguide/html_single/Hibernate_User_Guide.html#entity-pojo-constructor

JPA requires that this constructor be defined as public or protected. Hibernate, for the most part, does not care about the constructor visibility, as long as the system SecurityManager allows overriding the visibility setting. That said, the constructor should be defined with at least package visibility if you wish to leverage runtime proxy generation.

ReferenceURL : https://stackoverflow.com/questions/2935826/why-does-hibernate-require-no-argument-constructor

반응형