Hibernate.orgCommunity Documentation
When combined with Hibernate ORM, Ehcache is commonly used as a 2nd level cache to cache data whose primary storage is a relational database. When used with Hibernate OGM it is not "just a cache" but is used as the main (and exclusive) storage engine for your data.
This is not the reference manual for Ehcache itself: we’re going to list only how Hibernate OGM should be configured to use Ehcache; for all the tuning and advanced options please refer to the Ehcache Documentation.
This version of Hibernate OGM is compatible with Ehcache version 2.6.9. Other versions might work, but this is the only version which has been regularly tested with this version of Hibernate OGM.
Two steps:
And then choose one of:
To add the dependencies via some Maven-definitions-using tool, add the following module:
<dependency>
<groupId>org.hibernate.ogm</groupId>
<artifactId>hibernate-ogm-ehcache</artifactId>
<version>5.0.4.Final</version>
</dependency>
If you’re not using a dependency management tool, copy all the dependencies from the distribution in the directories:
/lib/required
/lib/ehcache
/lib/provided
Hibernate OGM expects you to define an Ehcache configuration in its own configuration resource; all what we need to set it the resource name.
To use the default configuration provided by Hibernate OGM - which is a good starting point for new users - you don’t have to set any property.
Ehcache datastore configuration properties
ehcache
.org/hibernate/ogm/datastore/ehcache/default-ehcache.xml
.hibernate.ogm.datastore.keyvalue.cache_storage
The strategy for persisting data in EhCache.
The following two strategies exist (values of the org.hibernate.ogm.datastore.keyvalue.options.CacheMappingType
enum):
CACHE_PER_TABLE
: A dedicated cache will be used for each entity type, association type and id source table.CACHE_PER_KIND
: Three caches will be used: one cache for all entities, one cache for all associations and one cache for all id sources.Defaults to CACHE_PER_TABLE
. It is the recommended strategy as it makes it easier to target a specific cache for a given entity.
When bootstrapping a session factory or entity manager factory programmatically,
you should use the constants accessible via EhcacheProperties
when specifying the configuration properties listed above.
Common properties shared between stores are declared on OgmProperties
(a super interface of EhcacheProperties
).
For maximum portability between stores, use the most generic interface possible.
Depending on the cache mapping approach, Hibernate OGM will either:
CACHE_PER_TABLE
approach.store data in three different caches when using the CACHE_PER_KIND
approach:
ENTITIES
: is going to be used to store the main attributes of all your entities.ASSOCIATIONS
: stores the association information representing the links between entities.IDENTIFIER_STORE
: contains internal metadata that Hibernate OGM needs
to provide sequences and auto-incremental numbers for primary key generation.The preferred strategy is CACHE_PER_TABLE
as it offers both more fine grained configuration options
and the ability to work on specific entities in a more simple fashion.
To describe things simply, each entity is stored under a single key. The value itself is a map containing the columns / values pair.
Each association from one entity instance to (a set of) another is stored under a single key. The value contains the navigational information to the (set of) entity.
Each entity is represented by a map. Each property or more precisely column is represented by an entry in this map, the key being the column name.
Hibernate OGM supports by default the following property types:
java.lang.String
java.lang.Character
(or char primitive)java.lang.Boolean
(or boolean primitive); Optionally the annotations @Type(type = "true_false")
, @Type(type = "yes_no")
and @Type(type = "numeric_boolean")
can be used to map boolean properties to the characters 'T'/'F', 'Y'/'N' or the int values 0/1, respectively.java.lang.Byte
(or byte primitive)java.lang.Short
(or short primitive)java.lang.Integer
(or integer primitive)java.lang.Long
(or long primitive)java.lang.Integer
(or integer primitive)java.lang.Float
(or float primitive)java.lang.Double
(or double primitive)java.math.BigDecimal
java.math.BigInteger
java.util.Calendar
java.util.Date
java.util.UUID
java.util.URL
Hibernate OGM doesn’t store null values in Ehcache, setting a value to null is the same as removing the corresponding entry from Ehcache.
This can have consequences when it comes to queries on null value.
Entity identifiers are used to build the key in which the entity is stored in the cache.
The key is comprised of the following information:
CACHE_PER_KIND
strategy)In CACHE_PER_TABLE
, the table name is inferred from the cache name.
In CACHE_PER_KIND
, the table name is necessary to identify the entity in the generic cache.
Example 10.1. Define an identifier as a primitive type
@Entity
public class Bookmark {
@Id
private Long id;
private String title;
// getters, setters ...
}
Table 10.1. Content of the Bookmark
cache in CACHE_PER_TABLE
KEY | MAP ENTRIES | |
---|---|---|
["id"], [42] | id | 42 |
title | "Hibernate OGM documentation" |
Table 10.2. Content of the ENTITIES
cache in CACHE_PER_KIND
KEY | MAP ENTRIES | |
---|---|---|
"Bookmark", ["id"], [42] | id | 42 |
title | "Hibernate OGM documentation" |
Example 10.2. Define an identifier using @EmbeddedId
@Embeddable
public class NewsID implements Serializable {
private String title;
private String author;
// getters, setters ...
}
@Entity
public class News {
@EmbeddedId
private NewsID newsId;
private String content;
// getters, setters ...
}
Table 10.3. Content of the News
cache in CACHE_PER_TABLE
KEY | MAP ENTRIES | |
---|---|---|
[newsId.author, newsId.title], ["Guillaume", "How to use Hibernate OGM ?"] | newsId.author | "Guillaume" |
newsId.title | "How to use Hibernate OGM ?" | |
content | "Simple, just like ORM but with a NoSQL database" |
Table 10.4. Content of the ENTITIES
cache in CACHE_PER_KIND
KEY | MAP ENTRIES | |
---|---|---|
"News", [newsId.author, newsId.title], ["Guillaume", "How to use Hibernate OGM ?"] | newsId.author | "Guillaume" |
newsId.title | "How to use Hibernate OGM ?" | |
content | "Simple, just like ORM but with a NoSQL database" |
Since Ehcache has not native sequence nor identity column support,
these are simulated using the table strategy, however their default values vary.
We highly recommend you explicitly use a TABLE
strategy if you want to generate a monotonic identifier.
But if you can, use a pure in-memory and scalable strategy like a UUID generator.
Example 10.3. Id generation strategy TABLE using default values
@Entity
public class GuitarPlayer {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private long id;
private String name;
// getters, setters ...
}
Table 10.5. Content of the hibernate_sequences
cache in CACHE_PER_TABLE
KEY | NEXT VALUE |
---|---|
["sequence_name"], ["default"] | 2 |
Table 10.6. Content of the IDENTIFIERS cache in CACHE_PER_KIND
KEY | NEXT VALUE |
---|---|
"hibernate_sequences", ["sequence_name"], ["default"] | 2 |
As you can see, in CACHE_PER_TABLE
, the key does not contain the id source table name.
It is inferred by the cache name hosting that key.
Example 10.4. Id generation strategy TABLE using a custom table
@Entity
public class GuitarPlayer {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "guitarGen")
@TableGenerator(
name = "guitarGen",
table = "GuitarPlayerSequence",
pkColumnName = "seq"
pkColumnValue = "guitarPlayer",
)
private long id;
// getters, setters ...
}
Table 10.7. Content of the GuitarPlayerSequence
cache in CACHE_PER_TABLE
KEY | NEXT VALUE |
---|---|
["seq"], ["guitarPlayer"] | 2 |
Table 10.8. Content of the IDENTIFIERS cache in CACHE_PER_KIND
KEY | NEXT VALUE |
---|---|
"GuitarPlayerSequence", ["seq"], ["guitarPlayer"] | 2 |
Example 10.5. SEQUENCE id generation strategy
@Entity
public class Song {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "songSequenceGenerator")
@SequenceGenerator(
name = "songSequenceGenerator",
sequenceName = "song_sequence",
initialValue = 2,
allocationSize = 20
)
private Long id;
private String title;
// getters, setters ...
}
Table 10.9. Content of the hibernate_sequences
cache in CACHE_PER_TABLE
KEY | NEXT VALUE |
---|---|
["sequence_name"], ["song_sequence"] | 11 |
Table 10.10. Content of the IDENTIFIERS
cache in CACHE_PER_KIND
KEY | NEXT VALUE |
---|---|
"hibernate_sequences", "["sequence_name"], ["song_sequence"] | 11 |
Entities are stored in the cache named after the entity name when using the CACHE_PER_TABLE
strategy.
In the CACHE_PER_KIND
strategy, entities are stored in a single cache named ENTITIES
.
The key is comprised of the following information:
CACHE_PER_KIND
strategy)In CACHE_PER_TABLE
, the table name is inferred from the cache name.
In CACHE_PER_KIND
, the table name is necessary to identify the entity in the generic cache.
The entry value is itself a map which contains all the entity properties - or to be specific columns. Each column name and value is stored as a key / value pair in the map.
Example 10.6. Default JPA mapping for an entity
@Entity
public class News {
@Id
private String id;
private String title;
// getters, setters ...
}
Table 10.11. Content of the News
cache in CACHE_PER_TYPE
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["1234-5678"] | id | "1234-5678" |
title | "On the merits of NoSQL" |
Table 10.12. Content of the ENTITIES
cache in CACHE_PER_KIND
KEY | MAP ENTRIES | |
---|---|---|
"News", ["id"], ["1234-5678"] | id | "1234-5678" |
title | "On the merits of NoSQL" |
As you can see, the table name is not part of the key for CACHE_PER_TYPE
.
In the rest of this section we will no longer show the CACHE_PER_KIND
strategy.
Example 10.8. Embedded object
@Entity
public class News {
@Id
private String id;
private String title;
@Embedded
private NewsPaper paper;
// getters, setters ...
}
@Embeddable
public class NewsPaper {
private String name;
private String owner;
// getters, setters ...
}
Table 10.14. Content of the News
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["1234-5678"] | id | "1234-5678" |
title | "On the merits of NoSQL" | |
paper.name | "NoSQL journal of prophecies" | |
paper.owner | "Delphy" |
Example 10.9. @ElementCollection with one attribute
@Entity
public class GrandMother {
@Id
private String id;
@ElementCollection
private List<GrandChild> grandChildren = new ArrayList<GrandChild>();
// getters, setters ...
}
@Embeddable
public class GrandChild {
private String name;
// getters, setters ...
}
Table 10.16. Content of the associations_GrandMother_grandChildren
cache in CACHE_PER_TYPE
KEY | ROW KEY | ROW MAP ENTRIES | |
---|---|---|---|
["GrandMother_id"], ["granny"] | ["GrandMother_id", "name"], ["granny", "Leia"] | GrandMother_id | "granny" |
name | "Leia" | ||
["GrandMother_id", "name"], ["granny", "Luke"] | GrandMother_id | "granny" | |
name | "Luke" |
Table 10.17. Content of the ASSOCIATIONS
cache in CACHE_PER_KIND
KEY | ROW KEY | ROW MAP ENTRIES | |
---|---|---|---|
"GrandMother_grandChildren", ["GrandMother_id"], ["granny"] | ["GrandMother_id", "name"], ["granny", "Leia"] | GrandMother_id | "granny" |
name | "Leia" | ||
["GrandMother_id", "name"], ["granny", "Luke"] | GrandMother_id | "granny" | |
name | "Luke" |
Here, we see that the collection of elements is stored in a separate cache and entry. The association key is made of:
CACHE_PER_KIND
approach where all associations share the same cacheThe association entry is a map containing the representation of each entry in the collection. The keys of that map are made of:
Set
this is all of the columns)The value attack to that collection entry key is a Map containing the key value pairs column name / column value.
Example 10.10. @ElementCollection with @OrderColumn
@Entity
public class GrandMother {
@Id
private String id;
@ElementCollection
@OrderColumn( name = "birth_order" )
private List<GrandChild> grandChildren = new ArrayList<GrandChild>();
// getters, setters ...
}
@Embeddable
public class GrandChild {
private String name;
// getters, setters ...
}
Table 10.19. Content of the GrandMother_grandChildren
cache
KEY | ROW KEY | ROW MAP ENTRIES | |
---|---|---|---|
["GrandMother_id"], ["granny"] | ["GrandMother_id", "birth_order"], ["granny", 0] | GrandMother_id | "granny" |
birth_order | 0 | ||
name | "Leia" | ||
["GrandMother_id", "birth_order"], ["granny", 1] | GrandMother_id | "granny" | |
birth_order | 1 | ||
name | "Luke" |
Here we used an indexed collection and to identify the entry in the collection, only the owning entity id and the index value is enough.
Associations between entities are mapped like (collection of) embeddables except that the target entity is represented by its identifier(s).
Example 10.11. Unidirectional one-to-one
@Entity
public class Vehicule {
@Id
private String id;
private String brand;
// getters, setters ...
}
@Entity
public class Wheel {
@Id
private String id;
private double diameter;
@OneToOne
private Vehicule vehicule;
// getters, setters ...
}
Table 10.21. Content of the Wheel
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["W001"] | id | "W001" |
diameter | 0.0 | |
vehicule_id | "V_01" |
Example 10.12. Unidirectional one-to-one with @JoinColumn
@Entity
public class Vehicule {
@Id
private String id;
private String brand;
// getters, setters ...
}
@Entity
public class Wheel {
@Id
private String id;
private double diameter;
@OneToOne
@JoinColumn( name = "part_of" )
private Vehicule vehicule;
// getters, setters ...
}
Table 10.23. Content of the Wheel
cache
KEY | MAP ENTRIES | |
---|---|---|
"Wheel", ["id"], ["W001"] | id | "W001" |
diameter | 0.0 | |
part_of | "V_01" |
Example 10.13. Unidirectional one-to-one with @MapsId and @PrimaryKeyJoinColumn
@Entity
public class Vehicule {
@Id
private String id;
private String brand;
// getters, setters ...
}
@Entity
public class Wheel {
@Id
private String id;
private double diameter;
@OneToOne
@PrimaryKeyJoinColumn
@MapsId
private Vehicule vehicule;
// getters, setters ...
}
Table 10.25. Content of the Wheel
cache
KEY | MAP ENTRIES | |
---|---|---|
["vehicule_id"], ["V_01"] | vehicule_id | "V_01" |
diameter | 0.0 |
Example 10.14. Bidirectional one-to-one
@Entity
public class Husband {
@Id
private String id;
private String name;
@OneToOne
private Wife wife;
// getters, setters ...
}
@Entity
public class Wife {
@Id
private String id;
private String name;
@OneToOne(mappedBy="wife")
private Husband husband;
// getters, setters ...
}
Table 10.28. Content of the associations_Husband
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["wife"], ["bea"] | ["id", "wife"], ["alex", "bea"] | id | "alex" |
wife | "bea" |
Example 10.15. Unidirectional one-to-many
@Entity
public class Basket {
@Id
private String id;
private String owner;
@OneToMany
private List<Product> products = new ArrayList<Product>();
// getters, setters ...
}
@Entity
public class Product {
@Id
private String name;
private String description;
// getters, setters ...
}
Table 10.29. Content of the Basket
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["davide_basket"] | id | "davide_basket" |
owner | "Davide" |
Table 10.30. Content of the Product
cache
KEY | MAP ENTRIES | |
---|---|---|
["name"], ["Beer"] | name | "Beer" |
description | "Tactical Nuclear Penguin" | |
["name"], ["Pretzel"] | name | "Pretzel" |
description | "Glutino Pretzel Sticks" |
Table 10.31. Content of the associations_Basket_Product
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["Basket_id"], ["davide_basket"] | ["Basket_id", "products_name"], ["davide_basket", "Beer"] | Basket_id | "davide_basket" |
products_name | "Beer" | ||
["Basket_id", "products_name"], ["davide_basket", "Pretzel"] | Basket_id | "davide_basket" | |
products_name | "Pretzel" |
Example 10.16. Unidirectional one-to-many with @JoinTable
@Entity
public class Basket {
@Id
private String id;
private String owner;
@OneToMany
@JoinTable( name = "BasketContent" )
private List<Product> products = new ArrayList<Product>();
// getters, setters ...
}
@Entity
public class Product {
@Id
private String name;
private String description;
// getters, setters ...
}
Table 10.32. Content of the Basket
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["davide_basket"] | id | "davide_basket" |
owner | "Davide" |
Table 10.33. Content of the Basket
cache
KEY | MAP ENTRIES | |
---|---|---|
["name"], ["Beer"] | name | "Beer" |
description | "Tactical Nuclear Penguin" | |
["name"], ["Pretzel"] | name | "Pretzel" |
description | "Glutino Pretzel Sticks" |
Table 10.34. Content of the associations_BasketContent
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["Basket_id"], ["davide_basket"] | ["Basket_id", "products_name"], ["davide_basket", "Beer"] | Basket_id | "davide_basket" |
products_name | "Beer" | ||
["Basket_id", "products_name"], ["davide_basket", "Pretzel"] | Basket_id | "davide_basket" | |
products_name | "Pretzel" |
Example 10.17. Unidirectional one-to-many using maps with defaults
@Entity
public class User {
@Id
private String id;
@OneToMany
private Map<String, Address> addresses = new HashMap<String, Address>();
// getters, setters ...
}
@Entity
public class Address {
@Id
private String id;
private String city;
// getters, setters ...
}
Table 10.36. Content of the Address
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["address_001"] | id | "address_001" |
city | "Rome" | |
["id"], ["address_002"] | id | "address_002" |
city | "Paris" |
Table 10.37. Content of the associations_User_address
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["User_id"], "user_001"] | ["User_id", "addresses_KEY"], ["user_001", "home"] | User_id | "user_001" |
addresses_KEY | "home" | ||
addresses_id | "address_001" | ||
["User_id", "addresses_KEY"], ["user_001", "work"] | User_id | "user_002" | |
addresses_KEY | "work" | ||
addresses_id | "address_002" |
Example 10.18. Unidirectional one-to-many using maps with @MapKeyColumn
@Entity
public class User {
@Id
private String id;
@OneToMany
@MapKeyColumn(name = "addressType")
private Map<String, Address> addresses = new HashMap<String, Address>();
// getters, setters ...
}
@Entity
public class Address {
@Id
private String id;
private String city;
// getters, setters ...
}
Table 10.39. Content of the Address
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["address_001"] | id | "address_001" |
city | "Rome" | |
["id"], ["address_002"] | id | "address_002" |
city | "Paris" |
Table 10.40. Content of the associations_User_address
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["User_id"], "user_001"] | ["User_id", "addressType"], ["user_001", "home"] | User_id | "user_001" |
addressesType | "home" | ||
addresses_id | "address_001" | ||
["User_id", "addressType"], ["user_001", "work"] | User_id | "user_002" | |
addressesType | "work" | ||
addresses_id | "address_002" |
Example 10.19. Unidirectional many-to-one
@Entity
public class JavaUserGroup {
@Id
private String jugId;
private String name;
// getters, setters ...
}
@Entity
public class Member {
@Id
private String id;
private String name;
@ManyToOne
private JavaUserGroup memberOf;
// getters, setters ...
}
Table 10.41. Content of the JavaUserGroup
cache
KEY | MAP ENTRIES | |
---|---|---|
["jugId"], ["summer_camp"] | jugId | "summer_camp" |
name | "JUG Summer Camp" |
Table 10.42. Content of the Member
cache
KEY | MAP ENTRIES | |
---|---|---|
["member_id"], ["emmanuel"] | member_id | "emmanuel" |
name | "Emmanuel Bernard" | |
memberOf_jug_id | "summer_camp" | |
["member_id"], ["jerome"] | member_id | "jerome" |
name | "Jerome" | |
memberOf_jug_id | "summer_camp" |
Example 10.20. Bidirectional many-to-one
@Entity
public class SalesForce {
@Id
private String id;
private String corporation;
@OneToMany(mappedBy = "salesForce")
private Set<SalesGuy> salesGuys = new HashSet<SalesGuy>();
// getters, setters ...
}
@Entity
public class SalesGuy {
private String id;
private String name;
@ManyToOne
private SalesForce salesForce;
// getters, setters ...
}
Table 10.43. Content of the SalesForce
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["red_hat"] | id | "red_hat" |
corporation | "Red Hat" |
Table 10.44. Content of the SalesGuy
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["eric"] | id | "eric" |
name | "Eric" | |
salesForce_id | "red_hat" | |
["id"], ["simon"] | id | "simon" |
name | "Simon" | |
salesForce_id | "red_hat" |
Table 10.45. Content of the associations_SalesGuy
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["salesForce_id"], ["red_hat"] | ["salesForce_id", "id"], ["red_hat", "eric"] | salesForce_id | "red_hat" |
id | "eric" | ||
["salesForce_id", "id"], ["red_hat", "simon"] | salesForce_id | "red_hat" | |
id | "simon" |
Example 10.21. Unidirectional many-to-many
@Entity
public class Student {
@Id
private String id;
private String name;
// getters, setters ...
}
@Entity
public class ClassRoom {
@Id
private long id;
private String lesson;
@ManyToMany
private List<Student> students = new ArrayList<Student>();
// getters, setters ...
}
The "Math" class has 2 students: John Doe and Mario Rossi
The "English" class has 2 students: Kate Doe and Mario Rossi
Table 10.46. Content of the ClassRoom
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], [1] | id | 1 |
name | "Math" | |
["id"], [2] | id | 2 |
name | "English" |
Table 10.47. Content of the Student
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["john"] | id | "john" |
name | "John Doe" | |
["id"], ["mario"] | id | "mario" |
name | "Mario Rossi" | |
["id"], ["kate"] | id | "kate" |
name | "Kate Doe" |
Table 10.48. Content of the associations_ClassRoom_Student
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["ClassRoom_id"], [1] | ["ClassRoom_id", "students_id"], [1, "mario"] | ClassRoom_id | 1 |
students_id | "mario" | ||
["ClassRoom_id", "students_id"], [1, "john"] | ClassRoom_id | 1 | |
students_id | "john" | ||
["ClassRoom_id"], [2] | ["ClassRoom_id", "students_id"], [2, "kate"] | ClassRoom_id | 2 |
students_id | "kate" | ||
["ClassRoom_id", "students_id"], [2, "mario"] | ClassRoom_id | 2 | |
students_id | "mario" |
Example 10.22. Bidirectional many-to-many
@Entity
public class AccountOwner {
@Id
private String id;
private String SSN;
@ManyToMany
private Set<BankAccount> bankAccounts;
// getters, setters ...
}
@Entity
public class BankAccount {
@Id
private String id;
private String accountNumber;
@ManyToMany( mappedBy = "bankAccounts" )
private Set<AccountOwner> owners = new HashSet<AccountOwner>();
// getters, setters ...
}
David owns 2 accounts: "012345" and "ZZZ-009"
Table 10.50. Content of the BankAccount
cache
KEY | MAP ENTRIES | |
---|---|---|
["id"], ["account_1"] | id | "account_1" |
accountNumber | "X2345000" | |
["id"], ["account_2"] | id | "account_2" |
accountNumber | "ZZZ-009" |
Table 10.51. Content of the AccountOwner_BankAccount
cache
KEY | ROW KEY | MAP ENTRIES | |
---|---|---|---|
["bankAccounts_id"], ["account_1"] | ["bankAccounts_id", "owners_id"], ["account_1", "David"] | bankAccounts_id | "account_1" |
owners_id | "David" | ||
["bankAccounts_id"], ["account_2"] | ["bankAccounts_id", "owners_id"], ["account_2", "David"] | bankAccounts_id | "account_2" |
owners_id | "David" | ||
["owners_id"], ["David"] | ["owners_id", "banksAccounts_id"], ["David", "account_1"] | bankAccounts_id | "account_1" |
owners_id | "David" | ||
["owners_id", "banksAccounts_id"], ["David", "account_2"] | bankAccounts_id | "account_2" | |
owners_id | "David" |
While Ehcache technically supports transactions, Hibernate OGM is currently unable to use them. Careful!
If you need this feature, it should be easy to implement: contributions welcome! See JIRA OGM-243.