Why does Hibernate require no argument constructor

2020-01-23 10:33发布

The no-argument constructor is a requirement (tools like Hibernate use reflection on this constructor to instantiate objects).

I got this hand-wavy answer but could somebody explain further? Thanks

9条回答
SAY GOODBYE
2楼-- · 2020-01-23 11:07

Hibernate uses proxies for lazy loading. If you do no define a constructor or make it private a few things may still work - the ones that do not depend on proxy mechanism. For example, loading the object (with no constructor) directly using query API.

But, if you use session.load method() you'll face InstantiationException from proxy generator lib due to non-availability of constructor.

This guy reported a similar situation:

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

查看更多
爷、活的狠高调
3楼-- · 2020-01-23 11:09

Hibernate instantiates your objects. So it needs to be able to instantiate them. If there isn't a no-arg constructor, Hibernate won't know how to instantiate it, i.e. what argument to pass.

The hibernate documentation says:

4.1.1. Implement a no-argument constructor

All persistent classes must have a default constructor (which can be non-public) so that Hibernate can instantiate them using Constructor.newInstance(). It is recommended that you have a default constructor with at least package visibility for runtime proxy generation in Hibernate.

查看更多
▲ chillily
4楼-- · 2020-01-23 11:09

Actually, you can instantiate classes which have no 0-args constructor; you can get a list of a class' constructors, pick one and invoke it with bogus parameters.

While this is possible, and I guess it would work and wouldn't be problematic, you'll have to agree that is pretty weird.

Constructing objects the way Hibernate does (I believe it invokes the 0-arg constructor and then it probably modifies the instance's fields directly via Reflection. Perhaps it knows how to call setters) goes a little bit against how is an object supposed to be constructed in Java- invoke the constructor with the appropriate parameters so that the new object is the object you want. I believe that instantiating an object and then mutating it is somewhat "anti-Java" (or I would say, anti pure theoretical Java)- and definitely, if you do this via direct field manipulation, it goes encapsulation and all that fancy encapsulation stuff.

I think that the proper way to do this would be to define in the Hibernate mapping how an object should be instantiated from the info in the database row using the proper constructor... but this would be more complex- meaning both Hibernate would be even more complex, the mapping would be more complex... and all to be more "pure"; and I don't think this would have an advantage over the current approach (other than feeling good about doing things "the proper way").

Having said that, and seeing that the Hibernate approach is not very "clean", the obligation to have a 0-arg constructor is not strictly necessary, but I can understand somewhat the requirement, although I believe they did it on purely "proper way" grounds, when they strayed from the "proper way" (albeit for reasonable reasons) much before that.

查看更多
登录 后发表回答