ReleaseNotes - objectify/objectify GitHub Wiki
2024-01-03
- Remove recently introduced constraint preventing ObjectifyService.init() from being called more than once. You shouldn't do this in application code, but it's common for tests.
2023-11-27
- Objectify is easier to use with multiple datastores. Several methods have been deprecated; see UpgradeVersion6ToVersion61.
- Add support for OR queries in composite filters
- Make count() operations operate via server-side aggregation queries
- Add sum(), avg(), and aggregate() [aggregation queries|AggregationQueries]
- Add ofy().load().readTime() convenience method to perform queries with a ReadOption.readTime()
- Add support for IN/!IN queries (technically this was already present; they were "enabled" by updating the google-cloud-datastore jar dependency).
- Example applications have been added at https://github.com/objectify/objectify-examples
2022-10-05
- Fix the
.toLegacySafe()
format to exactly match the values returned by 6.0.7 (and prior) when you are not using namespaces.
2022-09-27
- Add support for not-equal filters (
!=
) - Add support for in and not-in filters (
IN
,!IN
) - Add support for composite filters (
.filter(Filter)
). OR support will be enabled as soon as it is available in the underlying Google SDK. - Add
.stream()
method to queries (eg,ofy().load().type(Foo.class).stream().map(...
) - Remove deprecated
Key.getString()
andKey.toWebSafeString()
methods (usetoUrlSafe()
instead) - Change
Key.getId()
to returnLong
instead oflong
. It was documented to return 0 when not numeric, but actually threw NPE. Now returns null. - Address a potential race condition when using memcached (issue #451)
- Accommodate namespaces in the
toLegacyUrlSafe()
value
WARNING: The toLegacyUrlSafe()
value changed slightly in this version to allow for namespaces, even if you aren't using namespaces. We recommend you use 6.0.9 instead, which fixes this issue.
2021-04-23
- Don't raise exceptions when memcache unreachable
2020-08-31
- Improve the error message when loading data that is incompatible with the Java schema
- Handle namespaces in legacy urlsafe string keys
2020-01-27
- Fixed a bug that might "forget" the setting of
ofy().cache(false)
orofy().namespace(...)
in queries - Fixed several places that
ofy().namespace()
was being ignored (notably, when saving entities). - Automatically batch requests that exceed datastore request count limits (ie, 1000 reads or 500 writes).
- Removed some long-deprecated methods.
2019-11-21
- Add support for
java.time.Instant
2019-07-29
- Allow some control over
MemcacheService
instantiation. - Minor performance improvements.
2019-06-03
- Explicit support for Namespaces
2019-01-29
- Fix
ofy().load().ids(long...)
autoboxing problem. - Better error handling when reading old-style GAE string keys.
2018-09-20
- Fix NPE when loading a collection field which has been previously stored as
null
in an entity (outside of Objectify).
2018-08-08
- Fix error when trying to fetch more than 1000 keys at a time
- Expose transaction handle
- Better exception when an error occurs deserializing a
@Serialize
field
2018-04-06
If upgrading from a previous version, be sure to read UpgradeVersion5ToVersion6!
- Made the cache implementation pluggable. See the constructor javadocs for
ObjectifyFactory
.
2018-02-15
- You must call one of the overloads of ObjectifyService.init() during your application bootstrap (see UpgradeVersion5ToVersion6).
- Creating a key from a string now accepts both the old-style ("agblahblahzxcpvouaw") and new-style urlsafe strings. You can generate them with
Key.toUrlSafe()
andKey.toLegacyUrlSafe()
. - Added
ofy().load().option(...)
to allow manual control of read consistency.
2018-01-29
- POJOs fields with the
@Serialize
annotation now load correctly even when the underlying data type isShortBlob
. This can happen if you write the data outside of Objectify.
2017-12-23
This is the first version of Objectify that works with the new Google Cloud SDK. A list of changes is being maintained here: https://github.com/objectify/objectify/wiki/UpgradeVersion5ToVersion6
2017-07-06
- Fixed issue causing the
alsoLoad
attribute of the@Subclass
annotation to be ignored.
2017-07-03
- Fixed bug in autoconversion of long unicode strings to Text, introduced in v5.1.18. The conversion limit is 1500 bytes not characters.
2017-06-28
- Fixed performance bug causing memcache operations even for non-cacheable entities.
2017-06-28
- At some point the max char limit for a String in the datastore was raised from 500 to 1500. Objectify's autoconvert-to-Text code now reflects this new higher limit.
2017-04-09
- Optimized performance of query
list()
; async query was not being kicked off until first element accessed, which means it wasn't actually async at all.iterable()
still has this undesirable behavior, althoughiterator()
is properly async.
2017-03-16
- Add
ofy().mandatoryTransactions(true)
to force users to create a transaction context for any save() or delete() operations. A useful defensive check.
2017-02-15
- Expose constructor for
EntityMemcache
which allowsMemcacheServiceFactory
to be passed in. No behavioral changes.
2016-12-23
- Ensure lifecycle events are fired in
ofy().load().fromEntity()
- Support fields of type
Number
2016-05-25
- Fixed bug causing collection fields to be ignored if they contain an empty nested subcollection.
2016-03-17
- User code can now attach arbitrary data to transaction contexts through the
TransactionImpl.bag
property.
2016-03-07
-
ShortBlob
properties are automatically converted tobyte[]
fields.byte[]
fields are still saved asBlob
.
2016-01-28
- Added
ofy().transact(Runnable)
overload for Java8/retrolambda users
2015-11-08
- With a few exceptions, @Load annotations no longer produce load effects in transactions. This reduces the tendency of @Load to bring in unwanted entity groups. Within transactions, @Parent relationships and @Load with explicitly activated groups will still force loading.
- Deferred saves within @OnSave methods now work properly.
-
execute(TxnType.REQUIRES_NEW)
now starts a new transaction like it's supposed to
2015-09-12
- Relaxes requirement that a class have the
@Entity
annotation to be used to create aKey<?>
. The kind will be the simplename of that class. Registered POJO entity classes still require the@Entity
annotation; this only affects key creation.
2015-08-30
- Classes marked
@Entity
which are stored embedded are allowed to have null keys. Previously, any@Id Long
fields had to be populated with a real value. Now they are allowed to be null, which will leave the underlyingEmbeddedEntity
with a null key. The underlying datastore allows this. Note that unlike with top level entities, saving a null@Id
does NOT autogenerate an id.
2015-08-09
-
Objectify.transactNew(count, work)
was documented as # of tries but behaved as # of retries. Behavior now reflects documentation - # of tries. - Added missing overload for
Query.filterKey(Object)
- In transactions, only the first layer of fetching is performed asynchronously. All subsequent loads (via @Load annotations) are performed synchronously when the first layer of entities are materialized. This eliminates a rare edge case that produced spurious 'transaction closed' exceptions during transaction collisions. Outside of transactions, all fetches are performed asynchronously as normal.
2015-02-04
- Fix NPE when doing kind() queries.
- Fix NPE when a null value is projected.
2015-01-06
- When an entity is explicitly saved or deleted, clear any pending deferred operations on that entity
- Fix NPE when projecting properties with null values
- Allow deleting of native Entity objects
- Added ofy().load().kind(...) method
- No longer need to de-hybridize IN and NOT queries
2014-12-01
- Fixed a cross-compilation problem which produced a corrupt artifact for 5.1.2. No other changes.
2014-11-27
Don't use this version; the published artifact is corrupt.
- Call superclass @OnSave methods before subclass @OnSave methods
- Allow deferred save of entities with autogenerated ids.
2014-10-13
- Fixed a problem with ObjectifyFilter re-entrancy that manifested when using
dispatch.forward()
.- Note that this means you will not be warned if you leak Objectify contexts via
ObjectifyService.begin()
- Note that this means you will not be warned if you leak Objectify contexts via
2014-10-09
- Added
ofy().defer()
andofy().flush()
- An exception will be thrown if you try to use Objectify without the ObjectifyFilter
- A new method for using Objectify outside of normal request handling (unit tests, remote api, etc)
If you are using Objectify outside of a normal GAE http request (eg, unit tests or the the remote api), there is a new method you must invoke. See javadocs for ObjectifyService.run()
. The old ObjectifyFilter.complete() method has been removed.
2014-09-29
IMPORTANT! Read the release notes for 5.0.
- Fixed distinct() projection queries
2014-09-23
IMPORTANT! Read the release notes for 5.0.
- Fixed a problem with projection of numeric types
- Added method
Key.toWebSafeString()
- Trim the condition in
Query.filterKey()
2014-06-08
IMPORTANT! Read the release notes for 5.0.
- Implemented projection queries.
- Fixed issue with collections as the value of an embedded map.
- Bumped versions of GAE SDK and Guava.
2014-04-20
IMPORTANT! Read the release notes for 5.0.
- Fix bug preventing @Id/@Parent fields from being defined in non-@Entity base classes.
2014-04-20
IMPORTANT! Read the release notes for 5.0.
- Fix bug causing "no registered subclass found" when embedded class field has an annotation.
- Added Query.orderKey()
- ofy().delete().entities() now accepts anything keylike, not just entity objects
2014-04-13 IMPORTANT! Objectify v5 drops support for the old embedded object format. If you use embedded objects, you must follow the UpgradeVersion4ToVersion5 instructions or you may lose data.
- Translation engine has been completely rewritten.
- @Embed annotation has been dropped; any nested classes are embedded.
- Collections of embedded objects can be nested without restriction.
- Embedded objects support polymorphism and lifecycle methods.
- Method handles are used to populate properties (better performance).
- Query supports composite filters.
Some annotations have changed; read UpgradeVersion4ToVersion5.
2014-04-12
-
Requires Appengine SDK 1.8.3 or newer
-
Fix index contamination when batch saving multiple entities with nested indexes in the new format.
2014-04-05
-
Requires Appengine SDK 1.8.3 or newer
-
Fix bug loading old embed format when an embedded list contains null nested embedded objects.
IMPORTANT! Read the 4.1 release notes below
2014-03-31
-
Requires Appengine SDK 1.8.3 or newer
-
Fix bug loading new format when you have an @EmbedMap which contains EmbeddedEntity.
-
Fix bug loading new format when you have an array which contains EmbeddedEntity.
IMPORTANT! Read the 4.1 release notes below
2014-03-28
-
Requires Appengine SDK 1.8.3 or newer
-
GWT source removed from jar and moved to separate project. Fixes compile problems with GAE SDK 1.9.1.
-
Changes the storage format of @Embed objects
IMPORTANT! READ THIS!
Objectify is changing the native format in which @Embed objects are stored. Instead of creating dot-separated property names, Objectify 4.1 can store objects using the new EmbeddedEntity
native storage type. You are strongly encouraged to migrate to this new storage type ASAP, because Objectify 5.0 will drop support for the old format entirely. The EmbeddedEntity
format will allow many features that cannot be supported with the current codebase.
When loading entities Objectify 4.1 will automatically detect the format and read correctly. It defaults to writing the legacy format. If you call ObjectifyFactory.setSaveWithNewEmbedFormat(true)
, Objectify will write with the new format. To convert your entire database, set this flag and load+save every entity which has an @Embed structure.
If you use the new storage format, you MUST NOT revert to a previous version of Objectify or you will LOSE DATA. However, you must migrate all data to the new format before Objectify 5.0.
This does not affect you if you do not use @Embed. If you have any questions, post them to the Objectify Google Group.
2014-03-19
-
Requires Appengine SDK 1.8.3 or newer
-
Map and List objects returned from Objectify can now be serialized.
-
Added ability to set explicit memcache error handler.
-
Added Query.reverse() method.
-
@EmbedMap now allows keys to be of type Key<?> in addition to String.
-
Anything can convert to Text, just like anything can convert to String.
-
Builds with JDK1.7.
2014-02-07
- Requires Appengine SDK 1.8.3 or newer
Since the first versions of Objectify, GAE's datastore API has expanded significantly with features (such as XG transactions and asynchrony) that fundamentally change how an API should work. Version 4 is a re-imagining of Objectify based on years of experience building GAE applications. The API and implementation have completely changed from Objectify v3; there's no way to produce a concise set of release notes. Please read all documentation from the beginning.
For v3 users, these two documents will help:
- DesignObjectify4
- UpgradeVersion3ToVersion4
Concise change notes will be maintained going forward.
2011-11-10
- Requires Appengine SDK 1.6.0 or newer
Please read the release notes for 3.1 beta 1. In addition:
- Always enables XG when starting a transaction on HRD
- Memcache integration now uses SDK 1.6.0 batch CAS operations for efficiency
- Added ObjectifyFactory.allocateIdRange()
- Changed Key<?>.toWebSafeString() (introduced in 3.1b1) to getString()
- Added a Key<?> constructor (and create() method) that takes a web safe string (ie getString())
- Added optional converters for joda time and money classes
- Added a varargs overload of Objectify.get(Key...)
2011-10-13
- Requires Appengine SDK 1.5.5 or newer
Note: The big change in 3.1 is that the memcache integration has been rewritten from scratch. On the plus side, the new cache will not go out of sync with the datastore, even under severe contention. On the down side, batch fetches are prohibitively slow. This will be resolved in a future version by the addition of batch CAS operations to the GAE SDK.
- Added API for XG transactions
- Completely rewritten cache code
- Added Key>.toWebSafeString() and a constructor to reconstitute the Key>
- Added ObjectifyFactory.allocateId() convenience method
- Several internal API changes.
2011-09-08
-
Requires Appengine SDK 1.4.0 or newer
-
Added methods Query.chunkSize() and Query.prefetchSize()
-
Experimental support for @Embedded Maps
-
Added a TimeZoneConverter so you can have TimeZone fields
-
Added a BigDecimalLongConverter which is not enabled by default
2011-04-22
- Requires Appengine SDK 1.4.0 or newer
IMPORTANT! Read the release notes for beta1 and beta2, in particular the note about breaking Key> serialization. If you have **serialized** Key> objects into persistent stores, this will affect you. Also, you will not be able to construct Key<?> objects from client-side GWT.
- Fixed NPE when fetching polymorphic entities not in the database.
- Fixed NPE when fetching collection field with raw type (missing generics).
2011-04-04
-
Requires Appengine SDK 1.4.0 or newer
-
Implemented Polymorphic persistence
-
Key> implementation changed - this WILL BREAK KEY SERIALIZATION. If you have serialized keys in a persistent structure, read the discussion of this issue on the mailing list. This only affects Key> in @Serialized fields; simple Key> properties and @Embedded Key>s are fine.
-
Fields now receive their @Indexed/@Unindexed default state from the class they are declared on rather than the final class in the inheritance hierarchy. This is a potential breaking change, although previous behavior was undocumented.
-
Added a Query.fetch() method to produce an async Iterable
-
Better error message if you try to register a nonstatic inner class
-
Loading embedded collections with a null value for the property itself no longer throws an exception.
-
Added IfEmpty and IfNotEmpty conditions
-
A number of internal APIs changed to support polymorphism.
2011-02-28
-
Requires Appengine SDK 1.4.0 or newer
-
Implemented asynchronous operations on
AsyncObjectify
-
Breaking change: Moved all classes in
com.googlecode.objectify.helper
tocom.googlecode.objectify.util
, includingDAOBase
-
Significant internal changes to support async API.
2010-12-13
-
Requires Appengine SDK 1.4.0 or newer
-
Added pluggable system for managing type conversions
-
Unwraps InvocationTargetExceptions in lifecycle callbacks
-
Made ObjectifyOpts.clone() public
-
Fixed bug when filtering by enums
-
Added a "Monotonic" helper class
2010-10-21
-
Requires Appengine SDK 1.3.8 or newer
-
Deprecated Query.countAll(), added Query.count() method which behaves better.
-
Deprecated Query.cursor(); added Query.startCursor() and Query.endCursor().
-
Added Query.clone()
-
Allows null @Parent keys.
-
Now handles java.sql.Date
-
Ignores synthetic fields (should make Groovy happier)
-
Now respects @Indexed/@Unindexed on entity base classes.
-
Added overrideable createDefaultOpts() method to ObjectifyFactory. Added clone() method to ObjectifyOpts.
-
@Id and @Parent fields are now included when you embed an entity in another entity.
-
Fixed a bug related to fields whose type base class name overlapped with entity names (eg, User)
2010-06-01
-
Requires Appengine SDK 1.3.2 or newer
-
Added typesafe ObjectifyFactory.allocateIds() methods.
-
Enums are persisted using the .name() method rather than .toString()
-
Added varargs versions of Objectify.put() and Objectify.get()
-
DAOBase now lets you use ObjectifyOpts
2010-04-22
-
Requires Appengine SDK 1.3.2 or newer
-
Added ObjectifyOpts parameter to begin()
-
Added optional session cache
-
Fixed automatic byte[] to Blob conversion
-
Added Query.list() and Query.listKeys() methods
-
Fixed filtering with IN operator on key and id columns
-
Lifecycle callbacks (@PostLoad and @PrePersist) can now take Objectify and/or Entity parameters
-
Removed the datastore retry mechanism - this is now built into the appengine SDK.
2010-03-25
-
Requires Appengine SDK 1.3.1 or newer
-
Changed return type of
Objectify.get(Class<? extends T> clazz, Iterable<S> idsOrNames)
toMap<S, T>
rather thanMap<Key<T>, T>
. This is a breaking change -
Added support for partial index conditions to @Indexed and @Unindexed
-
Added @NotSaved (with conditions)
-
Added @AlsoLoad as replacement for @OldName
-
Deprecated @OldName
-
Added
Objectify.getFactory()
method -
Added wrapper helper classes for Objectify, Query, and QueryResultIterator
2010-02-25
-
Requires Appengine SDK 1.3.1 or newer
-
Added @Unindexed and @Indexed class and field support
-
Fixed bugs in query Cursor and limit() support.
2010-02-18
-
Requires Appengine SDK 1.3.1 or newer
-
Added Cursor support
-
Added @PostLoad and @PrePersist callbacks
2010-02-10
-
Requires Appengine SDK 1.3.0 or newer
-
See 2.0rc1 and 2.0b1 release notes for significant changes since 1.0.3.
-
Changed ObjectifyFactory.createKey() to slightly-different ObjectifyFactory.getKey() and removed createKey() from ObjectifyService.
2010-02-09
-
Requires Appengine SDK 1.3.0 or newer
-
Adds memcache integration (write-through, transaction safe, negative caching, custom class expiration) with a @Cached annotation.
2010-02-07
-
Requires Appengine SDK 1.3.0 or newer
-
Completely new Query API.
-
OKey> has been renamed to Key>
-
Added @Embedded classes, collections, and arrays
-
Added GWT versions of all basic datastore types (Email, Link, GeoPt, etc)
-
Fields using the
transient
keyword will now be persisted. The@Transient
annotation is now the only way to tell Objectify to ignore a field. -
New architecture and many more unit tests!
2010-01-29
-
Requires Appengine SDK 1.3.0 or newer
-
Fixed a bug in batch delete.
2010-01-26
-
Requires Appengine SDK 1.3.0 or newer
-
Entity superclasses now processed correctly.
-
OKey now serializes properly in GWT.
-
Fixed classloader exception when using FetchOptions with datastore retries.
-
Better error msg if entity missing no-args constructor.
2010-01-22
-
Requires Appengine SDK 1.3.0 or newer
-
Added support for Enum types
-
Fixed OPreparedQuery.asSingle() when resultset was empty
-
Added full support for the common collection types
2010-01-13
-
Requires Appengine SDK 1.3.0 or newer
-
Initial release.