HHH-10162 Inheritance and L2 cache
by Christian Beikov
Hey guys,
Steve said I should start a discussion about the possible solution for
HHH-10162 <https://hibernate.atlassian.net/browse/HHH-10162> so here we go.
While debugging the issue, I found out that the proxy is created at
DefaultLoadEventListener.createProxyIfNecessary() where it IMO should
consult the 2L cache first by calling existing =
loadFromSecondLevelCache( event, persister, keyToLoad );. The fix looks
easy, but I am not sure of the implications. Obviously this will affect
performance a little since it has to consult the L2 cache now.
I tried to start a discussion in the Dev room, but so far only Andrea,
Vlad and Chris have commented this. Has anyone a different idea for
implementing this?
--
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*
7 years
6.0 - NativeQuery#getQueryReturns
by Steve Ebersole
For 6.0 we need to address a few problems with this method.
First, although largely minor, is that we have an API contract returning
SPI references.
The larger concern is a side-effect of this method in terms of clearing
previous registered returns if new returns have been added since the
previous call (if one) to `#getQueryReturns`. When any of the
`NativeQuery#addXYZ` methods are called, a "builder" is actually registered
under the covers. When `#getQueryReturns` is called all previously
registered returns are cleared and the currently open builders are executed
and their generated returns are added to the internal (emptied) list.
If this were a clean-room impl I would just add a `#register`-style method
to those return builders and skip the whole queuing of the builders. But
that is actually a very dangerous change to make now as it would mean that
existing apps using this API would still call `#addXYZ` but no returns
would actually be registered.
I guess the correct direction depends on whether this method is used and
for what purpose. So first, anyone know of usages of these methods either
from applications or integrations?
The "safest" option is to:
1. document this side-effect
2. deprecate this method - it should go away, or be rethought
And we'd still have to consider the return types. One option would be to
temporarily keep around the SPI forms (deprecated) and continue to return
those. Ideally we'd retro-deprecate these SPI contracts and the method
back on 5.2 maintenance release and just drop them on 6.0[1]. Of course if
anything we know of is using this method, we would need the alternative.
Thoughts? Opinions? Suggestions?
[1] See my earlier `Continue to add 5.2 deprecations for 6.0 work?` message
to this list
7 years, 5 months
Continue to add 5.2 deprecations for 6.0 work?
by Steve Ebersole
Per subject I wanted to come to a consensus as to how exact we want to be
in terms of continuing to add deprecations to 5.2 for ongoing 6.0 work.
Considering that these deprecations are meant to be a guide for users to
migrate to 6.0 I think we should try to be as complete as possible in this
effort, but wanted to hear other's views.
An alternative is the @EndOfLife annotation I have recently added to 6.0.
We could back port this annotation and use that instead; the reason being
that people complain when we deprecate something without being able to
specify its "replacement". This would be an option to do both. The
drawback is that this annotation obviously has no tie-in with javac - users
would have to go out of their way to find these.
7 years, 5 months
Feature Request: Encrypt sensitive data with an "encrypted store/filter"
by Sebastian Bicchi
Dear all,
this is my first Thread/Request on this mailing list and maybe I'm completely wrong here. If so - please excuse that and ignore this message.
Now back to topic: My small "start-up" was confronted with the problem of storing sensitive data in the database via hibernate. The data I cared most about were credentials to APIs, tokens, private keys for signing, etc., in other words: Data that our application needed in plaintext but also might help an attacker in case of a breach of the database. Also data that you not necessarily would reveal to an DBA, especially if you make use of managed databases (how much do you trust your database?).
So we implemented an encrypted key-value store. The encrypted key value store encrypts at the moment only the value of the stored key-value pair. We're working on encrypting the key (=ID) as well. Because you can't trust the file system of the web-app server as well as the database, the secure store needs to be initialized with a passphrase or keyfile at the start of the (web-)application. After initialization the encrypted kv store resides inside of "@Context HttpServletRequest" and is accessible by the Web-App. The key for de/encryption only resides inside the memory of the server. This is the big win - even if you get a database dump (and there are *a lot* of dumps on pastebin or in the darknet) you wont be able to decrypt the stored values. Also, if you get access to the file system - you wont be able to decipher the values.
The Class of the Encrypted Key Value store only lets you initialize it with a passphrase, but never read the passphrase nor the symmetric key. Nevertheless there is no perfect security: If an attacker obtains full root access to the web application server he will be able to get access to the keys by dumping the memory of the JVM. Also if there is an code execution weakness you might be able to obtain values - we counter measure that by using Java Security Manager. Only signed classes can will get access to the Encrypted Key Value Store. Also we set up a restriction on reflections.
Now my request/question: Do you think it would make sense to add an annotation "@Encrypted" to encrypt fields at ORM Level? In my opinion this would be a great security win for hibernate (even if the JPA doesn't define an "Encrypted Entity"). It would be very nice if you just annotate a field with "@Encrypted" and let a transparent encryption do the work.
There are several steps to archive this, but I think it is possible:
* Each entity needs an Initialization Vector
* It is possible to make use of "format preserving encryption" and therefore not breaking the schema with encryption
* Without format preserving encryption, the encrypted fields will be converted to an @Lob or at least some binary type
* The initialization of the application needs to be done by an user - there is no generic way to archive this without breaking the security
If you think that might be a good thing for hibernate, please advice were it should be implemented and I will try to do so.
Kind regards
Sebastian Bicchi
--------------------------------------------------
Sec-Research GmbH
Graf Starhemberggasse 6/4
1040 Vienna
Tel.: +43 (0)660/228 25 77
https://www.sec-research.com
FN445069p, Handelsgericht Wien
--------------------------------------------------
7 years, 6 months
HHH-11791
by Christian Bongiorno
On Mon, Jun 12, 2017 at 11:02 PM Christian Beikov <
christian.beikov(a)gmail.com> wrote:
> Hi,
>
> this might work for a limited set of use cases, but what exactly are you
> expecting from that approach? Performance might be a bit better, but
> that's probably negligible. Apart from that, I only see "encapsulation"
> or "ease of use with other languages" being your argument. Is that
> correct, or are there other reasons why you think constructor injection
> is a good fit here?
>
>
Encapsulation is one of the OO principles (PIE) so maintaining it is a good
thing as it prevents
unintended state change. Having a class with only 'getters' means that, for
example, if an instance of that class is used in a HashSet, there is no
`setter` that could subsequently alter the hashCode. This is a common
problem with Java and big reason project lombok exists.
Using constructor injection honors this.
My reasoning for this feature is definitely to support integration with
Kotlin which is very strict on encapsulation. When you declare something
`val foo:String` in Kotlin it is 100% immutable. Attempting to simply set
field access to `true` on foo won't help. It does, however, generate a
constructor for all declared parameters in data classes (AKA: Pojos) so
this is the obvious way to respect (true) immutability and still make use
of an ORM like hibernate.
> As soon as you have circular references between entities, you need a
> hybrid approach with setters for some attributes. How would you do lazy
> initialization of entities when some fields don't have a setter?
>
>
Circular references present a thorny issue for sure that can't simply be
resolved with lazy hydration; this is the eager approach. In my opinion,
and exception is in order (and, a nieve implementation of this feature
would naturally generate a stack overflow).
> I could imagine that a constructor is annotated with a marker annotation
> to make it selectable for this kind of hydration and allow the
> parameters of that constructor to be annotated to bind them to entity
> attributes. By default, the parameter names could be made use of to
> avoid cluttering code. With that information, you can select the
> constructor at boot time for entity types. After all, we know what kind
> of SQL is generated, it's based on the field metadata, so no need for
> the runtime overhead.
>
> I don't know what others think, but when thinking about a possible
> implementation, this seems like a real deep cut that touches many places.
>
You certainly would know better than me on the difficulty of implementation.
>
>
> Mit freundlichen Grüßen,
> ------------------------------------------------------------------------
> *Christian Beikov*
> Am 12.06.2017 um 23:47 schrieb Christian Bongiorno:
> > To work, yes. This would be an optional means of injecting. I was
> thinking
> > some code like this (very very rough):
> >
> > public void prep(DataSource source)
> > throws SQLException, NoSuchMethodException,
> > IllegalAccessException, InvocationTargetException,
> > InstantiationException {
> >
> > ResultSet resultSet = source.getConnection().createStatement()
> > .executeQuery("select * from User where false");
> > ResultSetMetaData metaData = resultSet.getMetaData();
> > Set<String> columnNames = new HashSet<>();
> >
> > for(int i = 1; i < metaData.getColumnCount(); i++) {
> > columnNames.add(metaData.getColumnName(i));
> >
> > }
> >
> > Constructor<?> toUse =
> Arrays.stream(User.class.getDeclaredConstructors())
> > .filter(c -> c.getParameterCount() == columnNames.size())
> > .filter(ctr ->
> Arrays.stream(ctr.getParameters()).map(Parameter::getName)
> >
> .allMatch(columnNames::contains)).findFirst().orElse(User.class.getConstructor());
> >
> > Object entity = null;
> > if(toUse != User.class.getConstructor()) {// means we found a
> > matching constructor
> > Object[] input = new Object[toUse.getParameterCount()];
> > int i = 0;
> > for (Parameter parameter : toUse.getParameters()) {
> > input[i++] = resultSet.getObject(parameter.getName());
> > }
> > entity = toUse.newInstance(input);
> > }
> > else {
> > entity = toUse.newInstance();
> > }
> > }
> >
> >
> > One question that comes up is which data set is the master of the match?
> >
> > Do we "Select the constructor that matches the ResultSet?" or "Do we
> > select the result set that matches the constructor?"
> >
> > Another thought is to use the existing field selection logic (find
> > properties on the Class) and then look for the matching constructor;
> which
> > is a very common paradigm.
> >
> > Finally: An annotation specifically indicating this might also be in
> order.
> >
> > Just getting the discussion started
> >
> >
> > On Mon, Jun 12, 2017 at 1:41 PM Vlad Mihalcea <mihalcea.vlad(a)gmail.com>
> > wrote:
> >
> >> Hi,
> >>
> >> Wouldn't that require all entities be compiled with?
> >>
> >> javac -parameters
> >>
> >> Vlad
> >>
> >> On Mon, Jun 12, 2017 at 10:19 PM, Christian Bongiorno <
> >> christian.bongiorno(a)gmail.com> wrote:
> >>
> >>> Now that java 8 supports named parameters it becomes possible
> (potentially
> >>> preferrable) to use constructor injection instead of circumventing
> >>> encapsulation to set values on private fields.
> >>>
> >>> This shows itself as a potential win when integrating with Kotlin with
> >>> disallows the circumvention quite forcefully. Meaning: without
> constructor
> >>> injection the object needs setters. And, if it has setters then it's
> >>> mutable which is against best practices.
> >>>
> >>> I propose optionally using constructor injection when marshalling an
> >>> object
> >>> from data sources in a DB. I am willing to make the changes if I know
> they
> >>> can/will be incorporated.
> >>>
> >>> Thoughts? Here is the ticket
> >>> https://hibernate.atlassian.net/browse/HHH-11791
> >>>
> >> _______________________________________________
> >>> hibernate-dev mailing list
> >>> hibernate-dev(a)lists.jboss.org
> >>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >>>
> >>
> > _______________________________________________
> > hibernate-dev mailing list
> > hibernate-dev(a)lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
7 years, 6 months
HHH-10622
by Gail Badner
Is there any plan to fix HHH-10622, or do applications need to be converted
to annotations to use enhancement in 5.0 forward?
Regards,
Gail
7 years, 6 months
6.0 - Dialect "initialization" proposal
by Steve Ebersole
Another change that has been discussed for a long time has been adding the
ability for Dialects to initialize themselves (or some "environment"
delegate) based on database/driver info including version info. The idea
would be to get out of having to define new Dialects just for some minor
update in a database or driver that Hibernate needs to be aware of - the
Dialect would be allowed to make that distinction itself based on access to
this info.
As hinted above, I am not sure yet if the best approach to this is to have
the Dialect configure itself (least disruptive) or have it configure some
"environment" (an expanded JdbcEnvironment maybe). But regardless, the
idea is the same.
The proposal centers around 2 contracts:
1. Dialect itself and some "Dialect#initialize" method
2. A way to give Dialect#initialize access to the needed information.
Let's start with (2) as it is the more defined. The basic idea would be
similar to the existing
`org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo` contract.
The initial idea is something like
https://gist.github.com/sebersole/5af5bc5456701054632dd0eb65403505
For (1) there is still the question of whether Dialect#initialize affects
the Dialect itself or generates some "environment" object. But assuming
that it affects the Dialect itself, we would have something as simple as:
DatabaseInformation dbInfo = resolveDatabaseInformation(...);
Dialect dialect = resolveDialect( dbInfo );
dialect.initialize( dbInfo );
Or if we decide it should produce an environment object, something like:
DatabaseInformation dbInfo = resolveDatabaseInformation(...);
Dialect dialect = resolveDialect( dbInfo );
TheEnvironment env = dialect.initialize( dbInfo );
To note, we pass DatabaseInformation into #resolveDialect because it needs
some of that info (database-name / driver-name mainly) to decide on the
Dialect.
The end game here is that we would have single Dialects per database. E.g.
we'd have just:
1. OracleDialect
instead of:
1. OracleDialect
2. Oracle8iDialect
3. Oracle9Dialect
4. Oracle9iDialect
5. Oracle10gDialect
6. Oracle12cDialect
7. ...
7 years, 6 months