property() uses a fast path for the common case that the expression is a bean property path.
This will then fall back to using parse() when that isn't the case.
- append() adds to the sql with NO parsing
- parse() adds to the sql with parsing to replace logical bean paths into table alias placeholder + db column
In DatabaseConfig.isAutoLoadModuleInfo() it only used the querybean generated class registration is classes.isEmpty(). Changing this so that it only uses the loadModuleInfo flag.
This means, unless loadModuleInfo is set to false the classes that register with ebean will be a combination of both the explicitly registered ones plus the classes from the querybean generated EbeanEntityRegister.
In addition, this changes the classes from List to Set.
The history behind this is that originally there was a "profileId" concept where that was a int value that could be used as an "id" for a transactional method that we wanted to profile.
That went away and then the idea was that bytecode enhancement would determine the line number and we would use that but that was a bad idea and we ended up with lineNumber always as 0.
These days with StackWalker and DProfileLocation we can do this better that way so yeah. A followup to this is to add to the api a boolean flag as to whether a profile location should be with line numbers (which can change frequently due to refactoring etc)
The reason for this is that as part of DefaultOrmQuery.copy() it uses
DefaultExpressionList.copy() and that assumed that expressions were
safe to share which is NOT the case for IN and EXISTS sub-query expressions
so InQueryExpression and ExistsQueryExpression
The effective fix for this is that DefaultExpressionList.copy() changes
to call SpiExpression.copy() and for InQueryExpression and ExistsQueryExpression
to implement that copy() by creating a copy of the sub-query.
A "side-fix" is that in DefaultOrmQuery.createExtraJoinsToSupportManyWhereClause()
it was creating an instance of ManyWhereJoins, then mutating it ... and if we
change that to only doing the assignment at the end (object assignment is atomic)
then racy access reading ManyWhereJoins would always get a fully completed non-mutating
instance of ManyWhereJoins. Noting this because it kind of points to where I think
the race condition is (in createExtraJoinsToSupportManyWhereClause()) but noting that
with the change to DefaultExpressionList.copy() this "side-fix" isn't required per say.
Moves the joda-time ScalarTypes into a new ebean-joda-time module. Include
the ebean-joda-time module in the classpath, and the extra types will be
service loaded (by DefaultTypeManager).
Due to the move and change of CsvReader using StringParser ScalarType no longer
needs that general convertFromMillis() method. Note that date and dateTime ScalarTypes
still retain this conversion method.
So the complexity cost doesn't justify itself against only being used
by CSV reader to validate when assigning a date/time format to a property
/ expression path.
For example, can apply a lower case underscore naming convention to the metrics names. This
can be done such that it doesn't have to be applied every time the metrics are collected and
reported.
Currently, lastAccessTime can mutate during cache trim processing. This fixes this issue by taking a copy of the lastAccessTime storing as lastAccessSort and using that for sorting for cache trim.
The design change is to use TenantAwareCache to deal with wrap/unwrap of tenant aware keys, removing any tenant awareness from the underlying cache implementations (DefaultServerCache, redis, hazelcast etc).