(Quick Reference)

1 Introduction - Reference Documentation

Authors: Kim A. Betti

Version: 0.8.3

1 Introduction

The MultiTenant - SingleDB plugin aims to make it easy to set up and develop a multi-tenant application based on Hibernate. A multi tenant application will let you run multiple users or customers in the same application instance without them being able to see or modify each others data.

So far this plugin works in "single database" mode. What this means is that all your tenants will share the same database and tables. Hibernate will re-write queries before they hit the database so only data belonging to the current tenant will be fetched. Do note that some companies won't allow you to store their data in the same database as other customers.

This is usually used on SaaS applications, where you can sign-in to have one 'instance' of the offered application so you'll probably have your own URL (username.app.com).

Check these links to read about Multi-Tenancy

1.1 This plugin vs. multi-tenant-core

Those of you who has been using the multi-tenant plugin for a while are probably using multi-tenant-core. This great plugin was unmaintained for a long time and suffered from a list of minor and major problems. The plugin made use of some classes from the unofficial sun.* package, had compatibility problems with recent versions of Grails and used some intrusive means in order to intercepting Hibernate Sessions and criteria. Another problem was that webflow support added a compile-time dependency to the webflow plugin. This caused web flow support to be dropped from the multi-tenant-core plugin.

At some point Scott Ryan took over maintenance of the plugin. A few months later the multi-tenant organization was formed on GitHub by a group of developers invested in the plugin. The organization was formed to drive the plugin development forward. The most serious problems mentioned above has been fixed in the current version of multi-tenant-core.

Kim A. Betti started working on webflow support without compile time dependency and a less intrusive way of intercepting Hibernate sessions. The result of this work was this plugin (multi-tenant-single-db). The original plan was to merge at least some of the solutions in this plugin back into multi-tenant-core, but the plugins has drifted further apart while refactoring and improving single-database mode.

  1. Merging the changes back into multi-tenant-core would introduce unnecessary dependencies (Hawk Eventing and Hibernate Hijacker) for those using the plugin in multi-database mode.
  2. Some of the changes in this plugin would break existing applications.
  3. Align the plugin more closely with the most common use cases.

Featuremulti-tenant-single-dbmulti-tenant-core
Multi database modeNoYes
Single database modeYes, based on Hibernate FiltersYes, based on Criteria / Query manipulation
HQL supportYes, based on Hibernate FiltersNo
Webflow supportYes, without compile time dependencyNo

Short version: If you want support for multi database mode then your only option is to go with multi-tenant-core.

1.2 Design goals

Main focus

  1. Focus on single-database mode, while trying to keep the door open for later support for database per tenant as long as it doesn't add too much complexity.
  2. Make sure that the webflow plugin is supported. Without forcing anyone to install it into their projects.
  3. Leverage existing Spring and Hibernate solutions where possible.
  4. Cover as much as possible with unit and integration tests (many features are very difficult to test properly)
  5. Re-think some design decisions and add more support for the most common use cases.

Very long term, possibly never (depending on interest and patches)

  1. Create a separate core plugin independent of Hibernate.
  2. Support multiple-database mode? Hibernate Shards? There are rumors on the street talking about Multi Tenant support in Hibernate 4.
  3. Implement support for name-of-latest-and-greatest-nosql-hype-here

1.3 Single database mode

This plugin is (at least for the time being) focusing solely on single database mode. What this means is that every tenant (user, customer..) shares that same database. Hibernate will filter all queries targeting multi-tenant domain classes before they hit the database.

With a multi database approach tenant data will be stored in separate databases. This is often a requirement from 'enterprise' customers like banks, governments where developers are outnumbered by lawyers by a factor off 5.

Pros

  • Tenants can be created and deleted without any maintenance overhead.
  • You can backup and restore everything in one operation.

Cons

  • Some backup scenarios are actually more difficult. In a multi database environment you can backup and restore individual tenants. This is obviously a lot more tricky if all tenants share one database.
  • You might run into database scaling challenges if your tenants produce a lot of data. You might look into key based partitioning in your database.

This is by no means a complete list, it's just a couple of points from the top of my head to give you an idea of what you're buying into, feel free to suggest more pros'n'cons.

1.3.1 Indexing your database

There is a great post regarding how to do it with grails + multi-tenant-single-db + mysql here: Grails: Multi tenant architecture and database indexes

Trivial example

If you just want to index your tenantId property to allow faster scans in your table, this would fit:

import grails.plugin.multitenant.core.annotation.MultiTenant

@MultiTenant class Animal {

String name

static mapping = { tenantIdIndex indexColumn: [name: "tenantId", type:Integer] } }

Multi-column indexes

Multi-column indexes are better to use when you know witch columns you have to index. Check the link above to understand how they work and how they can benefit your application.

If you want to define multi-column indexes on your domain classes you may take a look into grails-hibernate-hijacker docs to understand how its DLS achieves it.

import grails.plugin.multitenant.core.annotation.MultiTenant

@MultiTenant class User {

String username

static mapping = { tenantIdIndex indexColumn: [name: "tenantId", type:Integer] }

// This will allow fast lookup on tenant alone and in // combination with username. static indexes = { tenant_username_idx 'tenant_id', 'username' }

}

Support for the indexes DSL is provided by Hibernate Hijacker. This is an experimental feature and might change in the future.