Hibernate: state of the union

Emmanuel Bernard Platform Architect, Red Hat Inc. 2013-06-12 What’s in it for me

Overview of the Hibernate portfolio Discover new features or refresh memory Get a pick of what’s coming Emmanuel Bernard

Data platform architect JBoss EAP, JBoss Data Service, JBoss Data Grid Hibernate projects, Infinispan, Ceylon, Awestruct... Specification Podcasts JBoss Community Asylum http://asylum.jboss.org Les Cast Codeurs http://lescastcodeurs.com http://emmanuelbernard.com | @emmanuelbernard WFK EAP

Hibernate ORM

JPA 2.0 compliant (and many more) WFK EAP Multitenancy

One application instance serving several clients (tenants)

For ORMs Filter queries, isolate cache Simplify development

Three approaches WFK EAP Three approaches WFK EAP Multi-tenancy in Hibernate ORM

Supports database and schema approach discriminator planned for 5.x

Database access MultiTenantConnectionProvider Convention-based datasource lookup

Passing the tenant id (manual or via resolver) WFK EAP And then?

Code becomes mostly transparent

Session session = sessionFactory.withOptions() .tenantIdentifier(”elephant-inc”) .openSession(); WFK EAP Performance

No more JDBC proxy Read-only / immutable entities stored in 2LC Bytecode enhanced entity pointing to metadata 10%-33% throughput improvements before database bottleneck Much lower CPU usage too WFK EAP

Hibernate Envers

Historical and audit data WFK EAP Hibernate Envers

Store audit information transparently Help in retrieving Historical data

Transparent and not intrusive existing schema unchanged current data accessed the same minimal code change WFK EAP How does it work

Companion Historical entity created On insert/update/delete: data inserted on audit table All change in a single transaction consistent state one associated revision number revision number is global (like SVN) WFK EAP

Add Envers to your classpath Mark the entity

@Entity @Audited class Person { public getName() {...} [...] } WFK EAP

Look up by revision

@Injectincluding EntityManager navigation em;

AuditReader ar = AuditReaderFactory.get(em);

// Reading the person at revision 1 old_p = ar.find(Person.class, id, 1); String oldCity = old_p.getAddress().getCity(); WFK EAP Query per revision WFK EAP Query per revision

@Inject EntityManager em;

AuditReader ar = AuditReaderFactory.get(em);

List personsAtAddress = ar.createQuery() .forEntitiesAtRevision(Person.class, 12) .addOrder(AuditEntity.property("surname").desc()) .add( AuditEntity.property("address").eq(relatedEntityInstance) ) .setFirstResult(4).setMaxResults(2) .getResultList(); WFK EAP Query by entity history WFK EAP Validity audit strategy

Audit strategy: validity Store start and end revision for a change Slower on insert/update/deletes Much faster on queries Avoid subselects Replace them with between x and y RevisionEntity Add new fields atop rev number and date Track Entity type per revision and property changed Various

National Character Set via @Nationalized Logging Natural id with smarter cache Order by nulls first / last Roadmap for Hibernate ORM

JPA 2.1 New metamodel Faster boot in JBoss EAP OSGi Work on memory pressure Integration w/ schema management tools WFK

Hibernate Search

Full-text and spatial search for your application WFK Hibernate Search, what’s that?

Object Index Mapper Full-text search engine library based on Lucene API at the Object level

Integrates with Hibernate ORM, OGM and Infinispan Cluster friendly WFK Why making Hibernate Search?

Ease of use Lower barrier of entry for search You focus on query We bring the infrastructure and optimized patterns Scalable query computation Close to the application logic WFK Use case

Google-like search engine for your entities Return the “best” matching entities first Recover from typos / faulty orthography Find from words with the same meaning Find by synonyms Find exact phrases Find similar entities Regular query WFK

Faceting WFK What’s faceting WFK Steps

Build a facet request By price range, by brand, etc Apply facet request on a query Run query Retrieve the facet results Number of results per facet

Run query with a facet filter Return results matching selection WFK Example of faceting request

QueryBuilder builder = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity( Cd.class ).get(); FacetingRequest priceFacetingRequest = builder.facet() .name( "priceFaceting" ) .onField( "price" ) .range() .below( 1000 ).excludeLimit() .from( 1000 ).to( 1500 ).excludeLimit() .above( 1500 ) .orderedBy(FacetSortOrder.RANGE_DEFINITION_ORDER) .createFacetingRequest(); WFK Example of faceted query

// create a fulltext query Query luceneQuery = builder.all().createQuery(); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Cd.class );

// retrieve facet manager and apply faceting request FacetManager facetManager = fullTextQuery.getFacetManager(); facetManager.enableFaceting( priceFacetingRequest );

// get the list of Cds List cds = fullTextQuery.list();

// retrieve the faceting results List facets = facetManager.getFacets( "priceFaceting" ); for(Facet facet : facets) { display(facet.getValue(), facet.getCount()); // [1000-1500: 34] } WFK Example of faceted filtering

// apply first facet as additional search criteria facetManager.getFacetGroup( "priceFaceting" ) .selectFacets( facets.get( 0 ) );

// re-execute the query cds = fullTextQuery.list(); WFK

Spatial query WFK Indexing

Boolean query on longitude and latitude Good for small corpus (100k) Smaller index

Quad Tree Good for big corpus Works nice with heterogenous distribution

WFK Quad tree

1.1 1.2 2

1.3.1.1 1.3.1.2 1.4

3 4 WFK How to index

@Entity @Indexed @Spatial(spatialMode = SpatialMode.GRID) public class Hotel { @Latitude Double latitude; @Longitude Double longitude; [...] } WFK How to query

QueryBuilder builder = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity( Hotel.class ).get();

org.apache.lucene.search.Query luceneQuery = builder.spatial() .onDefaultCoordinates() .within( radius, Unit.KM ) .ofLatitude( centerLatitude ) .andLongitude( centerLongitude ) .createQuery();

org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery( luceneQuery, Hotel.class ); List results = hibQuery.list(); WFK More

Distance between a point and the query center Sort by distance Hibernate OGM

JPA for NoSQL Goals

Offer full JPA API and mapping support Offer JP-QL query support (limited) With “native” query binding Support NoSQL families (k/v, column, document, graph)

Model facilitator Declarative denormalization engine Declarative schema migration What we have

CRUD Polymorphic entities Associations (Very) simple queries Hibernate Search query support

Infinispan, EhCache, MongoDB, Neo4J How to use it

Change the persistence provider Adjust connection configurations That’s it :) EAP

Hibernate Validator

Constraint your domain model Bean Validation 1.1

Method and constructor validation CDI / Java EE / Others More integration with DI frameworks EL expressions in error messages Group conversion in object graphs Questions

Answers