1 / 29

Hibernate OGM - Object/Grid Mapper

Hibernate OGM is an ORM framework implementing JPA that supports multiple products like Infinispan, Ehcache, Redis, MongoDB, CouchDB, Neo4j, and Cassandra.

ellenberger
Download Presentation

Hibernate OGM - Object/Grid Mapper

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Mug Jan 2016

  2. MUG Hibernate OGM Markus Dorner markus.dorner@ebcont.com EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  3. Features Hibernate Object/Grid Mapper • JPA support • Interesting for projects already using an ORM framework implementing JPA • Supports multiple products • Key/Value: Infinispan; Ehcache; Redis (tech preview) • Document: MongoDB (Configuration) ; CouchDB (tech preview) • Graph: Neo4j • Wide-column: Cassandra (tech preview) EBCONT enterprisetechnologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  4. Overview Basics • Same mechanics as ORM frameworks implementing JPA • Reuse of modules e.g. JPQL processing engine • NoSQL drivers to interact with the underlying data-store • Map your data with JPA annotations • Persistence context • First level cache • Same pitfalls • flush, clear • Object dirty handling • JPQL query language support EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  5. Agenda Topics fortoday • Bootstrapping in Wildfly • Adding Hibernate OGM Module • persistence.xml • Mapping • CRUD • Basic operations • Hibernate Session object • JPQL • Native queries • Transactions EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  6. Bootstrapping Wildfly Configuration and dependencies • Add Hibernate OGM Module to Wildfly • Download the Module jar for your server version • hibernate-ogm-modules-wildfly9.4.2.0.Final • extract it to the wildfly modules directory • <wildfly home dir>\modules\system\layers\base • Maven Setup • Bom already provided for easier version management • Dependency in your pom to provided <dependency> <groupId>org.hibernate.ogm</groupId> <artifactId>hibernate-ogm-bom</artifactId> <version>4.2.0.Final</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.hibernate.ogm</groupId> <artifactId>hibernate-ogm-mongodb</artifactId> <scope>provided</scope> </dependency> EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  7. Classloading Defining deployment structures • Define deployment structure in your project war • \src\main\webapp\WEB-INF\jboss-deployment-structure.xml <jboss-deployment-structure> <deployment> <dependencies> <module name="org.hibernate" slot="ogm" services="export" /> <module name="org.hibernate.ogm.mongodb" slot="main" services="export" /> </dependencies> </deployment> </jboss-deployment-structure> EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  8. Configuring persistence unit Persistence.xml <persistence-unit name="mongodb" transaction-type="JTA"> <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider> <jta-data-source>java:/DefaultDS</jta-data-source> <class>com.ebcont.model.LogEntry</class> <properties> <property name="hibernate.transaction.jta.platform“ value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" /> <property name="jboss.as.jpa.providerModule" value="org.hibernate:ogm" /> <property name="hibernate.ogm.datastore.provider" value="mongodb" /> <property name="hibernate.ogm.datastore.database" value="ogm-eval" /> <property name="hibernate.ogm.datastore.host" value="localhost" /> <property name="hibernate.ogm.datastore.port" value="27017" /> <property name="hibernate.ogm.datastore.create_database“ value="true" /> </properties> </persistence-unit> EBCONT enterprisetechnologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  9. Mapping Annotations Overview • Mapping over XML possibleaswell. Not covered in thisslides. • @Table • Refers to the collection the entity is stored • @Id, @Column • @Embeddable • @ElementCollection • Associations @ManyToOne, @OneToOne, … EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  10. Collection level @Table @Entity @Table(name = "logs") public class LogEntry { • Control the name of the collection • Omitted @Table leads to LogEntryas collection name • Default naming is the class name • Hibernate OGM provides no DDL generation • Non-existing collections will be created • Possible to define custom naming strategies EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  11. Primary key Overview • @Id • Simplest case map field to _id • { "_id" : "ba3db765-c2b8-4cb0-b91c-afe7cd414873“ } • ObjectId encouraged. Can be enforced with @Type if you want to work with Strings. • @EmbeddedId • "_id" : { "role" : “admin", "user" : "max" } • @IdClass • Generated json equal to @EmbeddedId • @Id over multiple fields • No dot notation needed when referring to ID fields in JPQL @Id private String id; @EmbeddedId private UserRoleId id; @Entity @IdClass(UserRoleId.class) public class UserRole { EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  12. Embedded List @ElementCollection @ElementCollection private List<String> subsystems; • Stores the List as Array into the document • List is managed and changes flushed into the database • In the ORM world this Annotation was not very performant • Change on List caused deletion of all rows and a reinsert of all rows -> low performance in relational world • In MongoDB it is encouraged to embed lists for performance • Mind the 16MB document limit "subsystems" : [ "DEBIT", "PAYMENT" ] EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  13. Example @Entity @Table(name = "logs") @NamedQueries({ @NamedQuery(name=LogEntry.FIND_OTHERS, query="SELECT l FROM LogEntry l WHERE l.id <> :id") }) publicclassLogEntry { publicstaticfinal String FIND_OTHERS = "LogEntry.findOthers"; @Id private String id = java.util.UUID.randomUUID().toString(); @Temporal(TemporalType.TIMESTAMP) @Column(nullable = false) private Calendar logTimestamp = Calendar.getInstance(); @Embedded privateSystemDatasystemData; @ElementCollection(fetch = FetchType.EAGER) private List<String> subsystems; @Version privatelongversion; EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  14. Example - Json output > db.logs.findOne() { "_id" : "ba3db765-c2b8-4cb0-b91c-afe7cd414873", "logTimestamp" : "2016/01/15 15:23:13:367 +0100", "systemData" : { "eventType" : "READ", "systemId" : "SERVICEBUS-NODE1" }, "version" : NumberLong(0), "subsystems" : [ "DEBIT", "PAYMENT" ] } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  15. Associations Overview • Configurable with property in persistenxe.xml • hibernate.ogm.datastore.document.association_storage • IN_ENTITY (default): store association information within the entity • ASSOCIATION_DOCUMENT: store association information in a dedicated document per association • 2 ways supported to store this information • Configurable also on entity level annotation based • Not covered by JPA Annotations • e.g. @AssocationStorage • Programmatic configuration available too EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  16. Unidirectional one-to-one Strategy IN_ENTITY • Car Entity has no reference to its child relation • Wheel has a reference to its parent • @JoinColumn( name = “car" ) to control the field name • Reference: to-one-associations @Entity publicclass Car { @Id private String id; { "_id" :"V_01", "brand" : "Mercedes" } @Entity publicclass Wheel { @Id privateString id; @OneToOne privateCar car; { "_id" : "W001", "car_id" : "V_01" } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  17. Bidirectional one-to-one Strategy IN_ENTITY @Entity publicclass Car { @Id private String id; @OneToOne private Wheel wheel; • Car Entity has reference to its child relation • Wheel has a reference to its parent • { "_id" : "V_01", • "brand" : "Mercedes", • "wheel_id" : "W001" } @Entity publicclass Wheel { @Id privateString id; @OneToOne privateCar car; { "_id" : "W001", "car_id" : "V_01" } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  18. Unidirectional many-to-one Strategy IN_ENTITY • Json result similar to @OneToOne • Reference: to-many-associations @Entity publicclassMember { @Id private String id; private String name; @ManyToOne private JavaUserGroup memberOf; { "_id" : "jerome", • "name" : "Jerome", "memberOf_id" : "summer_camp" } { "_id" : “james", "name" : “James“ "memberOf_id" : "summer_camp" } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  19. Bidirectional many-to-one Strategy IN_ENTITY • @OneToMany keeps references in Array • @ManyToOne side @Entity publicclassSalesForce{ @Id private String id; private String corporation; @OneToMany(mappedBy = "salesForce") private Set<SalesGuy> salesGuys; { "_id" : "red_hat", "corporation" : "Red Hat", "salesGuys" : [ "eric", "simon" ] } { "_id" : "simon", "name" :"Simon", "salesForce_id" : "red_hat" } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  20. Bidirectional many-to-many Strategy IN_ENTITY @Entity publicclassAccountOwner { @Id private String id; @ManyToMany private Set<BankAccount> bankAccounts; • Both sides keep references in array • Account Owner • Bank Account { "_id" : "owner_1", "bankAccounts" : [ "account_1" ] } @Entity publicclassBankAccount { @Id private String id; private String accountNumber; @ManyToMany( mappedBy = "bankAccounts" ) private Set<AccountOwner> owners; { "_id" : "account_1", "accountNumber" : "X2345000“, "owners" : [ "owner_1", "owner2222" ] } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  21. Query Log Deeper look at generated Queries • save:ogm-eval.logs { "_id" : "eventId" , "logTimestamp" : "2016/01/21 11:56:04:686 +0100" , "systemData" : { "eventType" : "READ" , "systemId" : "SERVICEBUS-NODE1"} , "version" : 0} • save:ogm-eval.LogSubEvent { "_id" : "subEventId" , "logEntry_id" : "eventId" , "eventName" : "Log Event1"} • update:ogm-eval.logs { "_id" : "eventId"} { "$set" : { "subEvents" : [ "subEventId"]}} • update:ogm-eval.LogSubEvent { "_id" : "otherSubEventId"} { "$set" : { "logEntry_id" : "eventId" , "eventName" : "Log Event2"}} • update:ogm-eval.logs { "_id" : "eventId"} { "$set" : { "subEvents" : [ "subEventId" , "otherSubEventId"]}} • update:ogm-eval.logs { "_id" : "eventId"} { "$set" : { "subsystems" : [ "PAYMENT" , "DEBIT"]}} • Looks superfluous. Why not written on initial insert? (@ElementCollection) • Each @OneToMany Element triggers one update. • Reason: no real tx over collections EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  22. CRUD Insert • Default transaction attribute REQUIRED (default) • Starts transaction if none started • More to transactions later • Entity added to persistence context • Flush or commit inserts the document to the collection • Flush in ORM flushes the statements to the database, but the changes are only visible after commit • JPQL query triggers flush @Stateless @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) publicclassLogService { @PersistenceContext(name = "mongodb") privateEntityManager em; publicLogEntry log() { LogEntry entry = new LogEntry(); initSystemData(entry); initSubsystems(entry); em.persist(entry); returnentry; } } EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  23. CRUD Basic Entitymanageroperations • EntityManager#find(…) • Multiple calls of find do not trigger a find operation to MongoDB • Changes on the entity will be detected and updates flushed back to the database • Use em.clear() or em.detach(Object) to remove objects from the persistence context. • Need direct access to the Hibernate Session? • (org.hibernate.ogm.hibernatecore.impl.OgmSessionImpl) em.getDelegate() • EntityManager#remove(…) EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  24. JPQL Supported Language Elements • comparisons "<", "<=", "=", ">=“, ">“, “<>” • IS NULL and IS NOT NULL • booleanoperators AND, OR, NOT • LIKE, IN and BETWEEN • ORDER BY • inner JOIN on embedded collections • projections of regular and embedded properties • Not supported: • JP-QL functions in particular aggregation functions like count • JP-QL update and delete queries • Check documentation for more details on your provider. EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  25. JPQL Examples Supported Elements • projection of the entity property • select id, description from Hypothesis h where id = 16 • projection of the embedded properties • select h.address.streetfrom Hypothesis h where h.id = 16 • IN Statement • select h from Hypothesis h where h.position IN (2, 3, 4) • Range with named parameters • select h from Hypothesis h where h.orderBETWEEN :start and :end • More examples: JP-QL Functions EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  26. Native Queries Examples and Limitations • 2 ways of native queries supported • find queries specifying the search criteria only • queries specified using the MongoDB CLI syntax • db.collection.find( … • Experimental • Parameters not supported. Query#setParameter() will not work. // criteria-only find syntax String query1 = "{ $and: [ { name : 'Portia' }, { author : 'Oscar Wilde' } ] }"; Poem poem = (Poem) em.createNativeQuery( query1, Poem.class ).getSingleResult(); // projection via CLI-syntax String query4 = "db.WILDE_POEM.count({ 'name' : 'Athanasia' })"; Object[] count = (Object[]) em.createNativeQuery( query4 ).getSingleResult(); EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  27. Transaction Management Overview • MongoDB transactions • spanning multiple documents with $isolated • lock on collection, single thread mode during write • Does not work on sharded clusters • Spanning multiple collections not supported • Hibernate OGM provides transactions by flushing the persistence context as late as possible • Partial changes possible if error occurs during flush • No compensation logic out-of-the-box, but API to implement one • Transaction Attributes supported within the above limitations • See @TransactionAttribute on Class or Method level @Stateless @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) publicclassLogService { @PersistenceContext(name = "mongodb") privateEntityManager em; publicLogEntry log() { EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  28. Advantages The good • Container managed transactions • Easily combined with other persistence units • Declarative transaction configuration • Easier introduction to projects already using JPA • Team already knows the framework design principles • Step-by-step migration • Moving entities one by one from the relational database to MongoDB • service code may only need small adaptions • example audit log entity • Evaluate best NoSQL fit for your application • Switch products by switching the provider (hibernate.ogm.datastore.provider) • Integration with Hibernate Search EBCONT enterprise technologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

  29. Disadvantages The bad • The same pitfalls from ORM apply to OGM • Keep an eye on the persistence context • Detach unnecessary objects to free memory • n+1 problem • Mapping in a relational database differs from a schema-less database like MongoDB • e.g. Joins not effective • Use associations (@OneToMany, …) with care • fetch joins. Not recommended for large lists. • Dirty detection may be expensive with large embedded lists • No Parameters in native queries • Better use driver directly • No criteria API support yet EBCONT enterprisetechnologies, Millennium Tower, Handelskai 94–96, A–1200 Vienna

More Related