เหตุใด Hibernate จึงไม่ต้องการตัวสร้างอาร์กิวเมนต์


106

ตัวสร้างไม่มีอาร์กิวเมนต์เป็นข้อกำหนด (เครื่องมือเช่นไฮเบอร์เนตใช้การสะท้อนบนตัวสร้างนี้เพื่อสร้างอินสแตนซ์อ็อบเจ็กต์)

ฉันได้รับคำตอบที่เป็นคลื่น แต่ใครช่วยอธิบายเพิ่มเติมได้ไหม ขอบคุณ


7
FYI: ยืนยันว่าThe no-argument constructor is a requirement เป็นสิ่งที่ผิดและคำตอบทั้งหมดที่ดำเนินการอธิบายว่าทำไมเป็นเช่นนี้ได้โดยไม่ต้องตั้งคำถามว่านี่คือในความเป็นจริงเป็นเช่นนั้น (รวมถึงคำตอบที่ได้รับการยอมรับซึ่งได้รับแม้แต่เงินรางวัล) จะไม่ถูกต้อง ดูคำตอบนี้: stackoverflow.com/a/29433238/773113
Mike Nakis

2
จำเป็นหากคุณใช้ไฮเบอร์เนตเป็นผู้ให้บริการสำหรับ JPA
Amalgovinus

1
@MikeNakis คุณไมค์ไม่ถูกต้อง Hibernate ต้องการตัวสร้างเริ่มต้นเพื่อสร้างอินสแตนซ์อ็อบเจ็กต์หากคุณใช้ hibernate เป็นผู้ให้บริการ JPA (Amalgovinus) มิฉะนั้น Hibernate จะรายงานCaused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Studentเหมือนในกรณีที่ฉันเพิ่งพบ
Mushy

@Mushy คำถามถูกแท็กด้วย "hibernate" และ "orm" จะไม่ถูกแท็กด้วย "jpa" ไม่มีการพูดถึง JPA ในคำถาม
Mike Nakis

1
@MikeNakis ฉันยอมรับ Mike แต่ Hibernate ถูกใช้เป็นการใช้งาน "JPA" และไม่ได้ใช้ในกรณีที่ไม่มี "JPA" หรือ "ORM" ดังนั้นสมมติฐานที่จำศีลคือการใช้ "JPA"
Mushy

คำตอบ:


139

ไฮเบอร์เนตและรหัสโดยทั่วไปที่สร้างวัตถุผ่านการสะท้อนใช้Class<T>.newInstance()เพื่อสร้างอินสแตนซ์ใหม่ของคลาสของคุณ วิธีนี้ต้องการตัวสร้าง no-arg สาธารณะเพื่อให้สามารถสร้างอินสแตนซ์วัตถุได้ สำหรับกรณีการใช้งานส่วนใหญ่การจัดหาคอนสตรัคเตอร์แบบไม่มีอาร์กิวเมนต์ไม่ใช่ปัญหา

มีแฮ็กที่ใช้การทำให้เป็นอนุกรมที่สามารถแก้ไขได้โดยไม่ต้องมีตัวสร้างที่ไม่มีอาร์กิวเมนต์เนื่องจากการทำให้เป็นอนุกรมใช้เวทมนตร์ jvm เพื่อสร้างวัตถุโดยไม่ต้องเรียกใช้ตัวสร้าง แต่ไม่สามารถใช้ได้กับ VM ทั้งหมด ตัวอย่างเช่นXStreamสามารถสร้างอินสแตนซ์ของออบเจ็กต์ที่ไม่มีตัวสร้าง no-arg แบบสาธารณะ แต่โดยการเรียกใช้ในโหมดที่เรียกว่า "ขั้นสูง" ซึ่งพร้อมใช้งานบน VM บางเครื่องเท่านั้น (ดูลิงค์สำหรับรายละเอียด) นักออกแบบของ Hibernate เลือกที่จะรักษาความเข้ากันได้กับ VM ทั้งหมดดังนั้นจึงหลีกเลี่ยงกลเม็ดดังกล่าวและใช้วิธีการสะท้อนที่ได้รับการสนับสนุนอย่างเป็นทางการซึ่งClass<T>.newInstance()ต้องใช้ตัวสร้างที่ไม่มีอาร์กิวเมนต์


31
FYI: ผู้สร้างไม่จำเป็นต้องเปิดเผยต่อสาธารณะ สามารถมีการมองเห็นแพ็คเกจและ Hibernate ควรsetAccessible(true)อยู่
สีเทา

ฉันสามารถสร้าง Custom UserType ด้วยตัวสร้างที่ไม่ใช่ค่าเริ่มต้นเพื่อตั้งค่าฟิลด์ที่จำเป็นสำหรับการดำเนินการ
L-Samuels

1
สำหรับการอ้างอิงObjectInputStreamทำบางสิ่งตามบรรทัดsun.reflect.ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToGetInstanceOf, Object.class.getConstructor()).newInstance()สำหรับการสร้างอินสแตนซ์วัตถุโดยไม่มีตัวสร้างเริ่มต้น (JDK1.6 สำหรับ Windows)
SamYonnou

เรื่อง: It can have package visibility and Hibernate should setAccessible(true). ไม่itได้หมายความว่าเป็นชั้น instantiated ผ่านการสะท้อน? และHibernate should setAccessible(true)หมายความว่าอย่างไร?
Kevin Meredith

Objenesis ทำสิ่งนี้และใช้กันอย่างแพร่หลายในหลาย framework เช่น spring-data และ mockito github.com/easymock/objenesis
ltfishie

47

ไฮเบอร์เนตสร้างอินสแตนซ์วัตถุของคุณ ดังนั้นจึงจำเป็นต้องสามารถสร้างอินสแตนซ์ได้ หากไม่มีตัวสร้างที่ไม่มีอาร์กิวเมนต์ไฮเบอร์เนตจะไม่ทราบวิธีการสร้างอินสแตนซ์นั่นคืออาร์กิวเมนต์ที่จะส่งผ่าน

เอกสาร Hibernateพูดว่า:

4.1.1. ใช้ตัวสร้างที่ไม่มีอาร์กิวเมนต์

ทุกชั้นเรียนถาวรจะต้องมีการสร้างเริ่มต้น (ซึ่งอาจจะไม่เป็นสาธารณะ) เพื่อให้ Hibernate Constructor.newInstance()สามารถยกตัวอย่างได้โดยใช้ ขอแนะนำให้คุณมีตัวสร้างเริ่มต้นที่มีการมองเห็นแพ็กเกจเป็นอย่างน้อยสำหรับการสร้างพร็อกซีรันไทม์ในไฮเบอร์เนต


6
ในฐานะที่เป็นสำหรับการแสดงผลคอนสตรัคถ้าคุณกำลังใช้แจ้งให้ทราบล่วงหน้า v2.0 JPA ว่าJSR-317พูดว่า: นวกรรมิกไม่มีหาเรื่องต้องเป็นสาธารณะหรือการป้องกัน
José Andias

@Bozho สวัสดีครับฉันมีข้อสงสัยอย่างหนึ่งว่าหากไฮเบอร์เนตภายในให้ใช้ Constructor.newInstance () เพื่อสร้างอินสแตนซ์อ็อบเจ็กต์แล้วจะไฮเบอร์เนตกำหนดค่าลงในฟิลด์โดยไม่กำหนดตัวตั้งค่าได้อย่างไร?
Vikas Verma

ฉันไม่เข้าใจว่าทำไมฉันถึงเห็นคำเตือนนี้สำหรับคลาสย่อยที่ไม่ใช่แบบส่วนตัวของ @Embeddable ที่มีตัวสร้างแบบไม่มีอาร์กิวเมนต์สาธารณะ ...
Amalgovinus

Constructor.newInstance () รับอาร์กิวเมนต์ปัญหา (จริงๆแล้วไม่ใช่ปัญหา) กำลังแมปอาร์กิวเมนต์เหล่านั้น ไม่รู้ว่าทำไมการจำศีลจึงไม่สามารถแก้ปัญหานี้ได้ สำหรับการเปรียบเทียบ: คำอธิบายประกอบ @JsonCreator ใน Jackson ทำสิ่งนี้และมีประโยชน์มากมายจากวัตถุที่ไม่เปลี่ยนรูป
drrob


45

เอิ่มขอโทษทุกคน แต่ไฮเบอร์เนตไม่ต้องการให้คลาสของคุณต้องมีคอนสตรัคเตอร์แบบไม่มีพารามิเตอร์ ข้อกำหนดของJPA 2.0ต้องการและนี่เป็นเรื่องง่อยมากในนามของ JPA เฟรมเวิร์กอื่น ๆ เช่น JAXB ก็ต้องการเช่นกันซึ่งก็ถือว่าอ่อนแอมากในนามของเฟรมเวิร์กเหล่านั้น

(อันที่จริง JAXB ควรจะอนุญาตโรงงานเอนทิตี แต่มันยืนยันที่จะสร้างอินสแตนซ์โรงงานเหล่านี้ด้วยตัวเองโดยกำหนดให้พวกเขามี - เดาว่าอะไร - ตัวสร้างแบบไร้พารามิเตอร์ซึ่งในหนังสือของฉันดีพอ ๆ กับการไม่อนุญาตให้โรงงาน; ง่อยแค่ไหน !)

แต่ไฮเบอร์เนตไม่ต้องการสิ่งนั้น

Hibernate สนับสนุนกลไกการสกัดกั้น (ดู"Interceptor" ในเอกสารประกอบ ) ซึ่งช่วยให้คุณสามารถสร้างอินสแตนซ์วัตถุของคุณด้วยพารามิเตอร์ตัวสร้างที่ต้องการ

โดยพื้นฐานแล้วสิ่งที่คุณทำคือเมื่อคุณตั้งค่าไฮเบอร์เนตคุณจะส่งผ่านวัตถุที่ใช้org.hibernate.Interceptorอินเทอร์เฟซและไฮเบอร์เนตจะเรียกใช้instantiate()เมธอดของอินเทอร์เฟซนั้นเมื่อใดก็ตามที่ต้องการอินสแตนซ์ใหม่ของวัตถุของคุณดังนั้นการใช้วิธีการดังกล่าวของคุณสามารถทำได้newวัตถุของคุณในแบบที่คุณต้องการ

ฉันได้ทำในโปรเจ็กต์และมันได้ผลเหมือนมีเสน่ห์ ในโปรเจ็กต์นี้ฉันทำสิ่งต่างๆผ่าน JPA ทุกครั้งที่ทำได้และฉันจะใช้ฟีเจอร์ไฮเบอร์เนตเช่นตัวสกัดกั้นเมื่อฉันไม่มีตัวเลือกอื่น

ดูเหมือนว่าไฮเบอร์เนตจะค่อนข้างไม่ปลอดภัยเนื่องจากในระหว่างการเริ่มต้นระบบจะออกข้อความข้อมูลสำหรับแต่ละคลาสเอนทิตีของฉันบอกฉันINFO: HHH000182: No default (no-argument) constructor for classและclass must be instantiated by Interceptorหลังจากนั้นฉันจะสร้างอินสแตนซ์โดย interceptor และก็พอใจกับสิ่งนั้น

หากต้องการตอบคำถามส่วนหนึ่งของ "ทำไม" สำหรับเครื่องมืออื่นที่ไม่ใช่ไฮเบอร์เนตคำตอบคือ "ด้วยเหตุผลที่ไม่ดีอย่างแน่นอน" และสิ่งนี้ได้รับการพิสูจน์โดยการมีอยู่ของตัวสกัดกั้นที่จำศีล มีเครื่องมือมากมายที่สามารถรองรับกลไกบางอย่างที่คล้ายกันสำหรับการสร้างอินสแตนซ์อ็อบเจ็กต์ไคลเอ็นต์ แต่ไม่ทำดังนั้นพวกเขาจึงสร้างอ็อบเจ็กต์ด้วยตัวเองดังนั้นจึงต้องใช้คอนสตรัคเตอร์แบบไม่มีพารามิเตอร์ ฉันอยากจะเชื่อว่าสิ่งนี้เกิดขึ้นเพราะผู้สร้างเครื่องมือเหล่านี้คิดว่าตัวเองเป็นโปรแกรมเมอร์ระบบนินจาที่สร้างเฟรมเวิร์กที่เต็มไปด้วยเวทมนตร์เพื่อใช้โดยโปรแกรมเมอร์แอปพลิเคชันที่ไม่รู้ซึ่ง (พวกเขาคิดว่า) จะไม่เคยมี ความจำเป็นในการสร้างขั้นสูงเช่น ... แบบโรงงาน (ตกลง,คิดอย่างนั้น ฉันไม่จริงคิดอย่างนั้น ฉันล้อเล่น.)


1
สุดท้ายใครโดน! ฉันใช้เวลามากขึ้นกว่าที่ฉันชอบจัดการกับกรอบเหล่านี้ซึ่งบดบังกระบวนการสร้างอินสแตนซ์อ็อบเจ็กต์ (ซึ่งเป็นสิ่งสำคัญอย่างยิ่งสำหรับการเพิ่มการพึ่งพาที่เหมาะสมและสำหรับพฤติกรรมของวัตถุที่สมบูรณ์) นอกจากนี้การสะท้อนของ Java ช่วยให้คุณสร้างวัตถุโดยไม่ต้องใช้ newInstance () เมธอด getDeclaredConstructors อยู่ในการสะท้อน API ตั้งแต่ JDK 1.1 มันน่ากลัวมากที่นักออกแบบสเป็คของ JPA ละเลยเรื่องนี้
drrob

นี่เป็นสิ่งที่ไม่ถูกต้อง หากใช้ Hibernate เป็นผู้ให้บริการ JPA เพื่อการคงอยู่จะต้องมีตัวสร้างเริ่มต้นไม่เช่นนั้นสิ่งต่อไปนี้Caused by: org.hibernate.InstantiationException: No default constructor for entity: : hibernate.tutorial.Studentที่เกิดขึ้นเมื่อเร็ว ๆ นี้เนื่องจากjavax.persistence.*;มีการใช้งานและเฉพาะ org.hibernateเมื่อสร้างSession, SessionFactory, and Configuration
Mushy

2
@ Mushy นี่ถูกต้องอย่างสมบูรณ์เพราะ a) คำถามเกี่ยวกับการจำศีลโดยไม่ต้องพูดถึง JPA แม้แต่คำเดียวและ b) ฉันพูดถึงประโยคที่สองของคำตอบอย่างชัดเจนว่า JPA ต้องการตัวสร้างเริ่มต้นแม้ว่าจะไม่จำศีลก็ตาม
Mike Nakis

36

ไฮเบอร์เนตเป็นเฟรมเวิร์ก ORM ซึ่งสนับสนุนกลยุทธ์การเข้าถึงฟิลด์หรือคุณสมบัติ อย่างไรก็ตามไม่รองรับการทำแผนที่ตามตัวสร้าง - คุณต้องการอะไร? - เนื่องจากบางประเด็นเช่น

จะเกิดอะไรขึ้นหากชั้นเรียนของคุณมีตัวสร้างจำนวนมาก

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) session.get(Person.class, <IDENTIFIER>);

ตัวสร้างใดที่ไฮเบอร์เนตควรเรียกเพื่อดึงวัตถุบุคคล คุณมองเห็นไหม ?

และในที่สุดโดยใช้การสะท้อนไฮเบอร์เนตสามารถสร้างอินสแตนซ์คลาสผ่านตัวสร้างที่ไม่มีอาร์กิวเมนต์ ดังนั้นเมื่อคุณโทร

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

ไฮเบอร์เนตจะสร้างอินสแตนซ์วัตถุบุคคลของคุณดังนี้

Person.class.newInstance();

ซึ่งตามเอกสาร API

คลาสถูกสร้างอินสแตนซ์ราวกับว่าด้วยนิพจน์ใหม่ที่มีรายการอาร์กิวเมนต์ว่างเปล่า

นิทานสอนใจ

Person.class.newInstance();

เหมือนกับ

new Person();

ไม่มีอะไรอีกแล้ว


1
นี่เป็นคำอธิบายที่ยอดเยี่ยมที่สุดที่ฉันพบเกี่ยวกับคำถามนี้ คำตอบส่วนใหญ่ที่ฉันพบใช้คำศัพท์ทางเทคนิคที่เป็นหนอนหนังสือและไม่มีเนื้อหาใดอธิบายได้ว่าเป็นวิธีที่ยืดหยุ่นได้เหมือนที่คุณทำ ขอชื่นชมคุณและขอบคุณ!
The Dark Knight

1
นี่อาจเป็นเหตุผลของทีม Hibernate แต่ในความเป็นจริงปัญหาสามารถแก้ไขได้โดย (1) ต้องการคำอธิบายประกอบหรืออื่น ๆ ก็ต่อเมื่อใช้ตัวสร้างที่ไม่ใช่ค่าเริ่มต้นหากมีตัวสร้างเพียงตัวเดียวและ (2) ใช้ class.getDeclaredConstructors และใช้ Constructor.newInstance () แทน Class.newInstance () จำเป็นต้องมีการแม็ปที่เหมาะสมใน XML / คำอธิบายประกอบก่อน Java 8 แต่ทำได้ทั้งหมด
drrob

ตกลงดังนั้นไฮเบอร์เนตจึงสร้างวัตถุจากตัวสร้างเริ่มต้นจากนั้นใช้ตัวตั้งค่าสำหรับฟิลด์nameและage? ถ้าไม่เช่นนั้นจะใช้ตัวสร้างอื่นในภายหลัง?
tryHard

2
@tryingHard ใช่เมื่อสร้างอินสแตนซ์แล้วไฮเบอร์เนตจะใช้ตัวตั้งค่าหรือฟิลด์ - ขึ้นอยู่กับกลยุทธ์การเข้าถึง ตามค่าเริ่มต้นตำแหน่งของคำอธิบายประกอบ Id จะให้กลยุทธ์การเข้าถึงเริ่มต้น ดูdocs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/…
Arthur Ronald

6

ที่จริงคุณสามารถสร้างอินสแตนซ์คลาสที่ไม่มีตัวสร้าง 0-args คุณสามารถรับรายชื่อตัวสร้างของคลาสเลือกหนึ่งและเรียกใช้ด้วยพารามิเตอร์ปลอม

แม้ว่าจะเป็นไปได้และฉันคิดว่ามันจะใช้งานได้และจะไม่มีปัญหา แต่คุณจะต้องยอมรับว่ามันค่อนข้างแปลก

การสร้างอ็อบเจกต์ในแบบที่ Hibernate ทำ (ฉันเชื่อว่ามันเรียกใช้ตัวสร้าง 0-arg จากนั้นมันอาจจะปรับเปลี่ยนฟิลด์ของอินสแตนซ์โดยตรงผ่าน Reflection บางทีมันอาจจะรู้วิธีการเรียก setters) จะขัดกับวิธีการสร้างอ็อบเจกต์ใน Java- เรียกใช้ตัวสร้างด้วยพารามิเตอร์ที่เหมาะสมเพื่อให้วัตถุใหม่เป็นวัตถุที่คุณต้องการ ฉันเชื่อว่าการสร้างอินสแตนซ์อ็อบเจ็กต์แล้วทำการกลายพันธุ์นั้นค่อนข้าง "ต่อต้าน Java" (หรือฉันจะพูดว่าต่อต้าน Java เชิงทฤษฎีบริสุทธิ์) - และแน่นอนว่าถ้าคุณทำสิ่งนี้ผ่านการจัดการฟิลด์โดยตรงมันจะไปห่อหุ้มและสิ่งห่อหุ้มแฟนซีทั้งหมด .

ฉันคิดว่าวิธีที่เหมาะสมในการทำเช่นนี้คือการกำหนดในการทำแผนที่ไฮเบอร์เนตว่าวัตถุควรถูกสร้างอินสแตนซ์จากข้อมูลในแถวฐานข้อมูลโดยใช้ตัวสร้างที่เหมาะสม ... แต่สิ่งนี้จะซับซ้อนกว่า - หมายความว่าไฮเบอร์เนตทั้งสองจะเท่ากัน ซับซ้อนมากขึ้นการทำแผนที่จะซับซ้อนมากขึ้น ... และทั้งหมดจะ "บริสุทธิ์" มากขึ้น และฉันไม่คิดว่าสิ่งนี้จะได้เปรียบกว่าแนวทางปัจจุบัน (นอกเหนือจากความรู้สึกดีที่ได้ทำสิ่งต่างๆ "วิธีที่เหมาะสม")

ต้องบอกว่าและเมื่อเห็นว่าวิธีการไฮเบอร์เนตนั้นไม่ "สะอาด" มากนักภาระหน้าที่ที่จะต้องมีตัวสร้าง 0-arg นั้นไม่จำเป็นอย่างยิ่ง แต่ฉันสามารถเข้าใจข้อกำหนดได้บ้างแม้ว่าฉันจะเชื่อว่าพวกเขาทำโดย "วิธีที่เหมาะสมเท่านั้น "เหตุเกิดเมื่อพวกเขาหลงจาก" วิธีที่เหมาะสม "(แม้ว่าจะมีเหตุผลที่สมเหตุสมผล) มากก่อนหน้านั้น


5

ไฮเบอร์เนตจำเป็นต้องสร้างอินสแตนซ์อันเป็นผลมาจากการสืบค้นของคุณ (ผ่านการสะท้อน) ไฮเบอร์เนตต้องอาศัยตัวสร้างเอนทิตีที่ไม่มีอาร์กิวเมนต์ดังนั้นคุณต้องระบุตัวสร้างที่ไม่มีอาร์กิวเมนต์ อะไรไม่ชัดเจน?


ตัวprivateสร้างไม่ถูกต้องภายใต้เงื่อนไขใด ฉันเห็นjava.lang.InstantiationExceptionแม้จะมีตัวprivateสร้างสำหรับเอนทิตี JPA ของฉัน เอกสารอ้างอิง .
Kevin Meredith

ฉันลองคลาสโดยไม่มีตัวสร้างว่าง (แต่ใช้ตัวสร้าง args) และมันก็ใช้ได้ ฉันได้รับ INFO จากโหมดไฮเบอร์เนต "INFO: HHH000182: ไม่มีตัวสร้างเริ่มต้น (ไม่มีอาร์กิวเมนต์) สำหรับคลาสและคลาสที่ต้องสร้างอินสแตนซ์โดย Interceptor" แต่ไม่มีข้อยกเว้นและได้รับวัตถุจาก DB เรียบร้อยแล้ว
เขื่อนลิเจป

2

การสร้างออบเจ็กต์ด้วยตัวสร้างแบบไม่มีพารามิเตอร์ผ่านการสะท้อนนั้นง่ายกว่ามากจากนั้นเติมคุณสมบัติด้วยข้อมูลผ่านการสะท้อนแทนที่จะพยายามจับคู่ข้อมูลกับพารามิเตอร์ตามอำเภอใจของตัวสร้างที่กำหนดพารามิเตอร์ด้วยการเปลี่ยนชื่อ / การตั้งชื่อความขัดแย้งตรรกะที่ไม่ได้กำหนดภายในตัวสร้าง ชุดพารามิเตอร์ไม่ตรงกับคุณสมบัติของวัตถุและอื่น ๆ

ORM และ serializers จำนวนมากต้องการตัวสร้างแบบไม่มีพารามิเตอร์เนื่องจากตัวสร้างพารามิเตอร์ที่ผ่านการสะท้อนนั้นบอบบางมากและตัวสร้างแบบไม่มีพารามิเตอร์ให้ทั้งความเสถียรต่อแอปพลิเคชันและการควบคุมพฤติกรรมของอ็อบเจ็กต์แก่ผู้พัฒนา


ฉันขอยืนยันว่าการบังคับให้เกิดความไม่แน่นอนอย่างสมบูรณ์ในสิ่งที่อาจจำเป็นต้องเป็นอ็อบเจ็กต์โดเมนที่สมบูรณ์นั้นยังคงเปราะบางกว่า (ORM มีไม่มากนักหากเอนทิตีของคุณจำเป็นต้องเป็นถุงข้อมูลที่ไม่มีคุณลักษณะในการทำงานฉันมาที่นี่เพราะฉันต้องการ ตัวสร้าง แต่มีลำดับที่ไม่ได้กำหนดของการเรียกตัวตั้งค่าที่หลากหลายแทน) ... แต่ +1 เพราะคุณรับทราบว่าการสะท้อนสามารถทำได้บนตัวสร้างที่มี args :)
drrob

2

ไฮเบอร์เนตใช้พร็อกซีสำหรับการโหลดที่ขี้เกียจ หากคุณไม่กำหนดตัวสร้างหรือกำหนดให้เป็นแบบส่วนตัวบางสิ่งอาจยังใช้งานได้ - สิ่งที่ไม่ขึ้นอยู่กับกลไกของพร็อกซี ตัวอย่างเช่นการโหลดวัตถุ (โดยไม่มีตัวสร้าง) โดยตรงโดยใช้ Query API

แต่ถ้าคุณใช้วิธี session.load () คุณจะต้องเผชิญกับ InstantiationException จากตัวสร้างพร็อกซี lib เนื่องจากตัวสร้างไม่พร้อมใช้งาน

ผู้ชายคนนี้รายงานสถานการณ์ที่คล้ายกัน:

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


0

ดูข้อมูลจำเพาะภาษา Java ในส่วนนี้ที่อธิบายความแตกต่างระหว่างคลาสภายในแบบคงที่และไม่คงที่: http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3

คลาสภายในแบบคงที่มีแนวคิดไม่แตกต่างจากคลาสทั่วไปทั่วไปที่ประกาศในไฟล์. java

เนื่องจาก Hibernate จำเป็นต้องสร้างอินสแตนซ์ ProjectPK โดยอิสระจากอินสแตนซ์ Project ProjectPK จึงต้องเป็นคลาสภายในแบบคงที่หรือประกาศในไฟล์. java ของตัวเอง

การอ้างอิงorg.hibernate.InstantiationException: ไม่มีตัวสร้างเริ่มต้น


0

Hibernate ใช้ Reflection API เพื่อสร้างอินสแตนซ์ของ Entity beans โดยปกติเมื่อคุณเรียกใช้get()หรือload()วิธีการ วิธีClass.newInstance()นี้ใช้สำหรับสิ่งนี้และต้องใช้ตัวno-argsสร้าง ดังนั้นหากคุณไม่มีตัวสร้าง no-args ในถั่วเอนทิตีไฮเบอร์เนตจะไม่สามารถสร้างอินสแตนซ์ได้และคุณจะได้รับ HibernateException

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.