unj*_*nj2 92 java orm hibernate factory-pattern
无参数构造函数是一个要求(像Hibernate这样的工具在这个构造函数上使用反射来实例化对象).
我得到了这个手作波形的答案,但有人可以进一步解释吗?谢谢
mdm*_*dma 127
Hibernate和通常通过反射创建对象的代码Class<T>.newInstance()用于创建类的新实例.此方法要求public no-arg构造函数能够实例化该对象.对于大多数用例,提供无参数构造函数不是问题.
基于序列化的黑客可以解决没有无参数构造函数的问题,因为序列化使用jvm魔术来创建对象而不调用构造函数.但是并非所有虚拟机都可以使用此功能.例如,XStream可以创建没有公共no-arg构造函数的对象实例,但只能通过在所谓的"增强"模式下运行,该模式仅在某些VM上可用.(有关详细信息,请参阅链接.)Hibernate的设计人员肯定选择保持与所有VM的兼容性,因此避免了这些技巧,并使用官方支持的Class<T>.newInstance()需要无参数构造函数的反射方法.
Boz*_*zho 44
Hibernate实例化您的对象.所以它需要能够实例化它们.如果没有no-arg构造函数,Hibernate将不知道如何实例化它,即传递什么参数.
在Hibernate文档说:
4.1.1.实现无参数构造函数
所有持久化类都必须具有默认构造函数(可以是非公共的),以便Hibernate可以使用它们实例化它们Constructor.newInstance().建议您使用默认构造函数,至少在Hibernate中生成运行时代理的包可见性.
Mik*_*kis 37
呃,对不起大家,但是Hibernate并没有要求你的类必须有一个参数的构造函数.在JPA 2.0规范需要它,这是代表JPA的非常跛脚.像JAXB这样的其他框架也需要它,代表这些框架也是非常蹩脚的.
(实际上,JAXB据说允许实体工厂,但它坚持要自己实例化这些工厂,要求他们有一个 - 引用什么 - 无参数构造函数,在我的书中它与不允许工厂一样好;这是多么蹩脚!)
但是Hibernate并不需要这样的东西.
Hibernate支持拦截机制(参见文档中的"拦截器"),它允许您使用所需的任何构造函数参数来实例化对象.
基本上,你所做的是当你设置hibernate时你传递一个实现org.hibernate.Interceptor接口的对象,然后hibernate将instantiate()在需要你的一个对象的新实例时调用该接口的方法,所以你的方法的实现可以new你喜欢的任何方式的对象.
我在一个项目中完成了它,它就像一个魅力.在这个项目中,我尽可能通过JPA做事情,当我没有其他选择时,我只使用拦截器之类的Hibernate功能.
休眠似乎对此有些不安,在启动时它会发出一个信息消息我的每个实体类的,告诉我INFO: HHH000182: No default (no-argument) constructor for class和class must be instantiated by Interceptor,但后来对我做的拦截器实例化他们,这是高兴.
为了回答Hibernate以外的工具问题的"为什么"部分,答案是"绝对没有充分的理由",这可以通过hibernate拦截器的存在来证明.有许多工具可以支持客户端对象实例化的一些类似机制,但它们没有,因此它们自己创建对象,因此它们必须要求无参数构造函数.我很想相信这种情况正在发生,因为这些工具的创造者认为自己是忍者系统程序员,他们创造了充满魔力的框架,供无知的应用程序员使用,他们(他们认为)绝不会在他们最疯狂的梦想中拥有需要像...... 工厂模式这样的高级结构.(好吧,我很想这么想.我实际上并不这么认为.我在开玩笑.)
Art*_*ald 33
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) { ... }
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您处理的是一个不一致的问题,因为Hibernate不能假设应该调用哪个构造函数.例如,假设您需要检索存储的Person对象
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Run Code Online (Sandbox Code Playgroud)
Hibernate应该调用哪个构造函数来检索Person对象?你能看到吗你能明白吗 ?
2º最后,通过使用反射,Hibernate可以通过其无参数构造函数实例化一个类.所以当你打电话
Person person = (Person) session.get(Person.class, <IDENTIFIER>);
Run Code Online (Sandbox Code Playgroud)
Hibernate将实例化您的Person对象,如下所示
Person.class.newInstance();
Run Code Online (Sandbox Code Playgroud)
根据API文档
该类实例化为具有空参数列表的新表达式
故事的道德启示
Person.class.newInstance();
Run Code Online (Sandbox Code Playgroud)
类似于
new Person();
Run Code Online (Sandbox Code Playgroud)
没有其他的
实际上,您可以实例化没有0-args构造函数的类; 你可以得到一个类'构造函数的列表,选择一个并使用伪参数调用它.
虽然这是可能的,我想它会起作用而且不会有问题,你必须同意这很奇怪.
以Hibernate的方式构造对象(我相信它调用0-arg构造函数,然后它可能直接通过Reflection修改实例的字段.也许它知道如何调用setter)稍微反对一个对象应该如何构造Java-使用适当的参数调用构造函数,以便新对象是您想要的对象.我相信实例化一个对象然后改变它有点"反Java"(或者我会说,反纯理论Java) - 当然,如果你通过直接字段操作来做到这一点,那就是封装和所有那些花哨的封装东西.
我认为这样做的正确方法是在Hibernate映射中定义如何使用适当的构造函数从数据库行中的信息实例化对象......但这会更复杂 - 这意味着Hibernate将是均匀的更复杂的是,映射会更复杂......并且更加"纯粹"; 而且我认为这不会比当前的方法有优势(除了以"正确的方式"做事情感觉良好).
说到这一点,并且看到Hibernate方法不是很"干净",有一个0-arg构造函数的义务并不是绝对必要的,但我可以理解一些要求,尽管我相信它们是纯粹"正确的方式" "当他们在此之前偏离"正确的方式"(尽管有合理的理由)时,他们的理由.
| 归档时间: |
|
| 查看次数: |
75260 次 |
| 最近记录: |