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
Preventing duplicate ForeignKey generation
by Milo van der Zee
Hello all,
During development of applications I'm used to set the schema creation
to 'update' (hbm2ddl.auto = update). This makes life a bit easier.
Issue with the newer version of Hibernate is that the name of the
generated keys changed and so all keys are regenerated. For the large
databases I use this takes hours and has to be done every time a fresh
copy from production is taken to the development environment.
I do use meaningful names for the indexes where possible. But when using
abstract classes used by the entities that is not possible because the
same fields from the abstract are used by many entity classes and so
would end up having the same index names.
I checked the code that decides if the index needs to be created and
found that it only checks the name of the index. Not what the index
actually does. This is why I changed that piece of code to be a bit
smarter. It is desinged for simple constraints from one column to
another column. Not for multi to multi column indexes and constraints.
I created a Jira issue for it but nobody notices it and there are no
comments or anything else. So now I try it here :)
Jira HHH-10934 (https://hibernate.atlassian.net/browse/HHH-10934)
Code fragment I put in SchemaMigratorImpl.java:
private ForeignKeyInformation findMatchingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) {
if (foreignKey.getName() ==null) {
return null;
}
/*
* Find existing keys based on referencing column and referencedTable
*/
String referencingColumn = foreignKey.getColumn(0).getName();
String referencedTableName = foreignKey.getReferencedTable().getName();
Iterable<ForeignKeyInformation> existingForeignKeys = tableInformation.getForeignKeys();
for (ForeignKeyInformation existingKey : existingForeignKeys) {
Iterable<ColumnReferenceMapping> columnReferenceMappings = existingKey.getColumnReferenceMappings();
for (ColumnReferenceMapping mapping : columnReferenceMappings) {
String existingReferencingColumn = mapping.getReferencingColumnMetadata().getColumnIdentifier().getText();
String existingReferencedTableName = mapping.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName();
if (referencingColumn.equals(existingReferencingColumn) && referencedTableName.equals(existingReferencedTableName)) {
return existingKey;
}
}
}
// If not yet found check based on key name return tableInformation.getForeignKey(Identifier.toIdentifier(foreignKey.getName()));
}
Or if you prever the Java 8 way:
private ForeignKeyInformation findMatchingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) {
log.debug("findMatchingForeignKey");
if (foreignKey.getName() ==null)return null;
/*
* Find existing keys based on referencing column and referencedTable
*/
String referencingColumn = foreignKey.getColumn(0).getName();
String referencedTableName = foreignKey.getReferencedTable().getName();
Predicate<ColumnReferenceMapping> mappingPredicate = m -> referencingColumn.equals(m.getReferencingColumnMetadata().getColumnIdentifier().getText())
&& referencedTableName.equals(m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName());
for (ForeignKeyInformation existingKey : tableInformation.getForeignKeys()) {
boolean found = StreamSupport.stream(existingKey.getColumnReferenceMappings().spliterator(),false).anyMatch(mappingPredicate);
if (found)return existingKey;
}
// If not yet found check based on key name return tableInformation.getForeignKey(Identifier.toIdentifier(foreignKey.getName()));
}
The calling method does not use the returned value. It only checks if
the returned value is null or not. So this could also be cleaned by
changing the method to return a boolean and then remove the for loop in
java-8 and use flatmap. But first let us agree on the validity of the
idea to change this piece of code.
I hope anybody would like to have a look at it and if there is any
change that the idea (not this actual very quick/dirty implementation)
goes into the system I'll clean it up and do some actual tests for more
complex database structures. I did not even check the junit tests yet.
At the moment it is good enough for me but I think it could be something
more people would benefit from.
Thanks,
Milo van der Zee
7 years, 7 months
Hibernate Validator 6.0.0.Alpha2 is out with improved Bean Validation 2.0 support
by Guillaume Smet
Hi,
We released Hibernate Validator 6.0.0.Alpha2 today in coordination with the
2.0.0.Alpha2 release of Bean Validation.
We improved a lot of things since the latest alpha:
- improved support for container element constraints and cascading and most
notably the ability to declare them using XML configuration or the
programmatic API
- new constraints: @NotBlank, @NotEmpty, @Email are now defined in the
specification and we also added @Positive and @Negative. All these new
constraints are supported in 6.0.0.Alpha2
- some performance improvements: 6 is now significantly faster than 5.4 on
our benchmarks
As explained in the announce on in.relation.to [1], we are looking forward
to your feedback on these features.
Have a nice day!
[1] http://in.relation.to/2017/03/30/hibernate-validator-600-alpha2-out/
7 years, 9 months
Hibernate Validator 6 benchmarks results
by Guillaume Smet
Hi,
I ran some HV 6 benchmarks results this morning, following the profiling
campaign I did last week and prior to our 6.0.0.Alpha2 release, and got
some interesting results I thought worthwhile to share.
Results are in ops/ms and are from our own JMH benchmarks. The higher, the
better.
== 5.4.1.Final
Result
"org.hibernate.validator.performance.simple.SimpleValidation.testSimpleBeanValidation":
556.190 ±(99.9%) 3.985 ops/ms [Average]
(min, avg, max) = (537.875, 556.190, 570.387), stdev = 8.049
CI (99.9%): [552.205, 560.175] (assumes normal distribution)
Result
"org.hibernate.validator.performance.cascaded.CascadedValidation.testCascadedValidation":
288.429 ±(99.9%) 3.305 ops/ms [Average]
(min, avg, max) = (271.979, 288.429, 308.106), stdev = 6.677
CI (99.9%): [285.124, 291.734] (assumes normal distribution)
== Current master
Result
"org.hibernate.validator.performance.simple.SimpleValidation.testSimpleBeanValidation":
869.546 ±(99.9%) 14.734 ops/ms [Average]
(min, avg, max) = (760.007, 869.546, 909.206), stdev = 29.763
CI (99.9%): [854.813, 884.280] (assumes normal distribution)
Result
"org.hibernate.validator.performance.cascaded.CascadedValidation.testCascadedValidation":
343.699 ±(99.9%) 2.077 ops/ms [Average]
(min, avg, max) = (331.333, 343.699, 352.626), stdev = 4.196
CI (99.9%): [341.622, 345.776] (assumes normal distribution)
== Analysis
=== SimpleValidation
So, interestingly enough, current master is 56% faster than 5.4.1.Final on
the simple validation case.
This is all due to the fact that we now cache the ValueExtractor in the
metadata whereas the value unwrapper was determined at validation time
before. All the CPU goes here:
https://github.com/hibernate/hibernate-validator/blob/5.4/engine/src/main...
and especially on the typeResolver.resolve calls.
This is mostly a structural improvement due to the new design of
ValueExtractors (kudos Gunnar!).
=== CascadedValidation
So, last week, HV 6 was 3 times slower (yes **3 times** slower) than HV 5.4
on the CascadedValidation benchmark.
After my recent improvements, it's now 20% faster so it's quite conclusive
too. I obtained these results mostly by limiting the number of reflection
calls (again) and better caching of some metadata.
== Conclusion
So 2 conclusions mostly:
- we are on the right track
- we really need to be careful when doing reflection operations, they might
look harmless at the time but they consume a lot of cycles
Have a nice day!
--
Guillaume
7 years, 9 months
Documentation for people not using dependency management tools
by Sanne Grinovero
I'm brushing up some OGM documentation, and noting that we regularly
make examples for both people consuming Maven pom definitions, and
people downloading our distribution and trying to figure out which
jars they need.
I am not aware of specific problems with the instructions we give, but
they all look highly suspicious; instructions are incomplete at best
as we don't go into details.
And we don't test these either.. I'm confident that if I were to test
these instructions most would be out of date.
While I'm aware that some people still don't use dependency management
tools; I'm inclined to remove these documentation sections and abandon
this population to their fate... at least we'd be slimming down the
docs a bit for the sake of most developers.
Any strong objections?
If we really want to keep these, it would be great to have a
documentation section generated from the maven dependencies but I
don't think this is our priority now.
Thanks,
Sanne
7 years, 9 months
6.0 - id type
by Steve Ebersole
In all versions of Hibernate to-date we have required that the Java type of
an id be Serializable. Strictly speaking JPA has no such restriction - it
says ids can be any Object type *unless* the entity is to be serialized, in
which case the id must be Serializable (duh).
As we transition into 6.0, I wonder if we want to loosen this restriction
and allow the id to be any Object type as well. There really is no valid
reason (beyond the obvious case explicitly discussed in the JPA spec) for
requiring the id to be Serializable.
WDYT?
7 years, 9 months
Re: [hibernate-dev] Javassist dependency conflict in the ORM modules for WildFly
by Sanne Grinovero
On 28 March 2017 at 17:28, Steve Ebersole <steve(a)hibernate.org> wrote:
>
>
> On Tue, Mar 28, 2017 at 11:12 AM Sanne Grinovero <sanne(a)hibernate.org>
> wrote:
>>
>> Hi Scott,
>>
>> no I don't think that's possible. There are many ways of bootstrapping
>> Hibernate, and "using code" is also a valid option, which implies end
>> users have the option to read configuration properties from custom
>> sources or even hard-code configuration.
>>
>> Granted in practice they'll likely use Spring or other frameworks to
>> boot it, but a list of such frameworks would necessarily be
>> open-ended.
>>
>> Not least, I wouldn't want you to automatically add Hibernate ORM
>> dependencies as it's very likely in most of these cases that the end
>> user will want to use a different version of Hibernate ORM to match
>> the requirements of the framework do jour, or otherwise include a
>> custom version.
>>
>> The only "safe default" would be to inspect the bytecode of the
>> deployment and see if both conditions are true:
>> - any class refers to Hibernate (JPA) code / annotations
>> - no Hibernate version is included
>
>
> You mean strictly in terms of whether to inject Hibernate dependencies I
> guess. Because this does not give Scott what he asked for. As I mentioned
> to Scott on HipChat, the only possible "auto" choice I can see is whether
> the app includes a persistence.xml, but even that can be inaccurate.
>
> So ultimately I think there should also be a deployment flag to be the
> definitive answer to whether we should "inject Hibernate" because the user
> "asked for it".
+1
Above I'm just trying to describe why any other alternative is not safe.
Not least, any reasonable user will prefer a configuration line over
some unclear, automagic strategy.
I'd highly prefer consistency, especially when it comes to
dependencies I'll have on classpath.
Thanks,
Sanne
7 years, 9 months
Javassist dependency conflict in the ORM modules for WildFly
by Sanne Grinovero
Hi all,
there's a conflict in the Javassist versions of the WildFly modules of
Hibernate ORM 5.2.4.Final, but I'm not sure how to proceed as I'm not
familiar with this functionality.
The module declares *both*:
- a dependency to the WildFly provided Javassist: <module
name="org.javassist"/>
- inclusion of Hibernate's own version of Javassist: <resource-root
path="javassist-3.20.0-GA.jar"/>
Having both is causing trouble as they are both visible to the
Hibernate classloader; however I couldn't score a quick win with the
testsuiste by disabling either (all tests using these modules in the
Hibernate Search testsuite fail).
I suspect the problem is that JipiJapa also depends on the <module
name="org.javassist"/>, while ORM obviously needs the more recent
version of it.
I'm not familiar with what JipiJapa's business around Javassist; could
we keep the two clearly separated?
Especially if we want to make Byte Buddy a viable alternative, I
suspect the solution is that JipiJapa should not depend on Javassist
directly, but invoke a generic instrumentation SPI on Hibernate; also
with JipiJapa not able to see Javassist at all, we'd be in control of
the one and only Javassist version visible to ORM: the one we compile
and test with.
Thanks,
Sanne
7 years, 9 months