blob: e309cdac4464a34d9a117898acf3372e4cc87c42 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>Using VPD Multi-Tenancy | EclipseLink 2.7 Understanding EclipseLink</title>
<meta name="generator" content="Oracle DARB XHTML Converter (Mode = document) - Version 1.0.22 Build 1" />
<meta name="date" content="2014-06-10T10:35:15Z" />
<meta name="robots" content="noarchive" />
<meta name="doctitle" content="Using VPD Multi-Tenancy" />
<meta name="relnum" content="Release 2.7" />
<link rel="stylesheet" type="text/css" href="../../dcommon/style.css" media="screen" />
<link rel="copyright" href="../../dcommon/html/cpyr.htm" title="Copyright" type="text/html" />
<link rel="start" href="../../index.htm" title="Home" type="text/html" />
<link rel="contents" href="toc.htm" title="Contents" type="text/html" />
<link rel="prev" href="multitenancy003.htm" title="Previous" type="text/html" />
<link rel="next" href="multitenancy005.htm" title="Next" type="text/html" />
<!-- START: Disqus --><script type="text/javascript"> var disqus_developer = 0; </script><!-- END: Disqus --><!-- START: Sharethis --><script type="text/javascript">var switchTo5x=true;</script><script type="text/javascript" src="http://w.sharethis.com/button/buttons.js"></script><script type="text/javascript" src="http://s.sharethis.com/loader.js"></script> <!-- END: Sharethis --></head>
<body bgcolor="#FFFFFF"><iframe id="docheader" frameborder="0" framemargin="0" scrolling="no" src="../../dcommon/header.html"></iframe><script src="http://www.google.com/jsapi" type="text/javascript"></script><script type="text/javascript"> google.load('search', '1', {language : 'en'}); google.setOnLoadCallback(function() { var customSearchOptions = {}; var googleAnalyticsOptions = {}; googleAnalyticsOptions['queryParameter'] = 'q'; googleAnalyticsOptions['categoryParameter'] = ''; customSearchOptions['googleAnalyticsOptions'] = googleAnalyticsOptions; var customSearchControl = new google.search.CustomSearchControl( '016171230611334810008:enkkfjmsqju', customSearchOptions); customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET); var options = new google.search.DrawOptions(); options.setSearchFormRoot('cse-search-form'); customSearchControl.draw('cse', options); }, true);</script><link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" /><div id="cse" style="width:100%;"></div>
<div class="header"><a id="top" name="top"></a>
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td align="left" valign="top"><font face="helvetica, arial, sans-serif"><b>EclipseLink Solutions Guide for EclipseLink</b><br />
Release 2.7</div></td>
<td valign="bottom" align="right" width="144">
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td>&nbsp;</td>
<td align="center" valign="top"><a href="toc.htm"><img src="../../dcommon/images/contents.png" alt="Go To Table Of Contents" border="0" height="16" width="16" /><br />
</td><td>&nbsp;</td><td align="center"><a href="../../" target="_top" class="external text" title="Search" rel="nofollow"><img src="../../dcommon/images/search.png" alt="Search" style="border:0;" /><br /><span class="mini"></span></a></td><td>&nbsp;</td><td align="center"><a href="../eclipselink_otlcg.pdf" title="PDF" target="_blank"><img src="../../dcommon/images/pdf_icon.png" style="padding-right:5px;border:0" alt="PDF"></a></td>
</tr>
</table>
</td>
</tr>
</table>
<hr />
<table class="navigation simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100" align="center">
<tr>
<td align="center"><a href="multitenancy003.htm"><img src="../../dcommon/images/larrow.png" alt="Previous" border="0" height="16" width="16" /></a></td>
<td align="center"><a href="multitenancy005.htm"><img src="../../dcommon/images/rarrow.png" alt="Next" border="0" height="16" width="16" /></a></td>
<td>&nbsp;</td>
</tr>
</table>
</div>
<!-- class="header" -->
<div class="ind"><!-- End Header --><a id="CHDJEBAC" name="CHDJEBAC"></a><a id="TLADG501" name="TLADG501"></a>
<div class="sect1"><!-- infolevel="all" infotype="General" -->
<h1 class="sect1"><font face="arial, helvetica, sans-serif" color="#330099">Using VPD Multi-Tenancy</font></h1>
<p>A Virtual Private Database (VPD) uses security controls to restrict access to database objects based on various parameters.</p>
<p>For example, the Oracle Virtual Private Database supports security policies that control database access at the row and column level. Oracle VPD adds a dynamic <code>WHERE</code> clause to SQL statements issued against the table, view, or synonym to which the security policy was applied.</p>
<p>Oracle Virtual Private Database enforces security directly on the database tables, views, or synonyms. Because security policies are attached directly to these database objects, and the policies are automatically applied whenever a user accesses data, there is no way to bypass security.</p>
<p>When a user directly or indirectly accesses a table, view, or synonym that is protected with an Oracle Virtual Private Database policy, Oracle Database dynamically modifies the SQL statement of the user. This modification creates a WHERE condition (called a predicate) returned by a function implementing the security policy. Oracle Virtual Private Database modifies the statement dynamically, transparently to the user, using any condition that can be expressed in or returned by a function. Oracle Virtual Private Database policies can be applied to SELECT, INSERT, UPDATE, INDEX, and DELETE statements.</p>
<p>When using EclipseLink VPD Multitenancy, the database handles the tenant filtering on all SELECT, INSERT, UPDATE, INDEX and DELETE queries.</p>
<p>To use EclipseLink VPD multi-tenancy, you must first configure VPD in the database and then specify multi-tenancy on the entity or mapped superclass, as shown in the following example, using <code>@Multitenant</code> and <code>@TenantDiscriminatorColumn</code>:</p>
<a id="TLADG626" name="TLADG626"></a>
<div class="sect2"><a id="sthref96" name="sthref96"></a>
<h2 class="sect2"><font face="arial, helvetica, sans-serif" color="#330099">Main Tasks for Using VPD Multi-Tenancy</font></h2>
<p>The following tasks provide instructions for using VPD multi-tenancy with Oracle Virtual Private Database:</p>
<ul>
<li>
<p><a href="#CHDDEDCJ">Task 1: Prerequisites</a></p>
</li>
<li>
<p><a href="#CHDDFBFC">Task 2: Configure the Virtual Private Database</a></p>
</li>
<li>
<p><a href="#CHDICCHE">Task 3: Configure the Entity or Mapped Superclass</a></p>
</li>
<li>
<p><a href="#CHDDJIAE">Task 4: Disable Criteria Generation</a></p>
</li>
<li>
<p><a href="#CHDIIJEB">Task 5: Configure persistence.xml</a></p>
</li>
</ul>
<a id="CHDDEDCJ" name="CHDDEDCJ"></a><a id="TLADG1130" name="TLADG1130"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" -->
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 1: Prerequisites</font></h3>
<p>To implement and use VPD multi-tenancy, you need:</p>
<ul>
<li>
<p>EclipseLink 2.4 or later.</p>
<p>Download EclipseLink from <code><a href="http://www.eclipse.org/eclipselink/downloads/">http://www.eclipse.org/eclipselink/downloads/</a></code>.</p>
</li>
<li>
<p>Any compliant Java Database Connectivity (JDBC) database that supports VDP, for example, Oracle Virtual Private Database.</p>
<p>For the certification matrix, see</p>
</li>
</ul>
</div>
<!-- class="sect3" -->
<a id="CHDDFBFC" name="CHDDFBFC"></a><a id="TLADG627" name="TLADG627"></a>
<div class="sect3">
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 2: Configure the Virtual Private Database</font></h3>
<p>In this example, an Oracle Virtual Private Database is configured with a policy and a stored procedure. The policy is a call to the database that tells the database to use a stored function to limit the results of a query. In this example, the function is called <code>ident_func</code>, and it is run whenever a <code>SELECT</code>, <code>UPDATE</code> or <code>DELETE</code> is performed on the <code>SCOTT.TASK</code> table. The policy is created as follows:</p>
<pre xml:space="preserve" class="oac_no_warn">
CALL DBMS_RLS.ADD_POLICY ('SCOTT', 'TASK', 'todo_list_policy', 'SCOTT', 'ident_func', 'select, update, delete'));
</pre>
<p>The function defined below is used by VPD to limit the data based on the identifier that is passed in to the connection. The function uses the <code>USER_ID</code> column in the table to limit the rows. The rows are limited, based on what is set in the <code>client_identifier</code> variable in the <code>userenv</code> context.</p>
<pre xml:space="preserve" class="oac_no_warn">
CREATE OR REPLACE FUNCTION ident_func (p_schema IN VARCHAR2 DEFAULT NULL, p_object IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
AS
BEGIN
RETURN 'USER_ID = sys_context(''userenv'', ''client_identifier'')';
END;
</pre></div>
<!-- class="sect3" -->
<a id="CHDICCHE" name="CHDICCHE"></a><a id="TLADG629" name="TLADG629"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" -->
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 3: Configure the Entity or Mapped Superclass</font></h3>
<p>As described above, VPD is configured to use the <code>USER_ID</code> column to limit access to rows. Therefore, you must tell EclipseLink to auto-populate the <code>USER_ID</code> column on inserts. The following code uses EclipseLink multi-tenancy and specifies that the client identifier is passed in to the entity managers using a property called <code>tenant.id</code>. Because the filtering is done by VPD on the database, you must turn off caching on this entity to avoid leakage across users.</p>
<pre xml:space="preserve" class="oac_no_warn">
@Entity
@Multitenant(VPD)
@TenantDiscriminatorColumn(name = "USER_ID", contextProperty = "tenant.id")
@Cacheable(false)
public class Task implements Serializable {
...
...
</pre></div>
<!-- class="sect3" -->
<a id="CHDDJIAE" name="CHDDJIAE"></a><a id="TLADG630" name="TLADG630"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" -->
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 4: Disable Criteria Generation</font></h3>
<p>When single-table and table-per-tenant multi-tenancy are enabled, a client identifier is auto appended to any generated SQL. However, when VPD is used to limit the access to data, the auto-appending of the identifier should be turned off.</p>
<p>Beginning with EclipseLink 2.4, disable criteria generation as follows:</p>
<pre xml:space="preserve" class="oac_no_warn">
@Multitenant(includeCriteria=false)
@TenantDiscriminatorColumn(name = "USER_ID", contextProperty = "tenant.id")
</pre>
<p>In EclipseLink 2.3.1, you must run the following codefrom a <code>SessionCustomizer</code>:</p>
<pre xml:space="preserve" class="oac_no_warn">
session.getDescriptor(Task.class).getQueryManager().setIncludeTenantCriteria(false);
</pre></div>
<!-- class="sect3" -->
<a id="CHDIIJEB" name="CHDIIJEB"></a><a id="TLADG631" name="TLADG631"></a>
<div class="sect3"><!-- infolevel="all" infotype="General" -->
<h3 class="sect3"><font face="arial, helvetica, sans-serif" color="#330099">Task 5: Configure persistence.xml</font></h3>
<p>Add the following properties to <code>persistence.xml</code>.</p>
<p>Include the following to set and clear the VPD identifier:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;property name="eclipselink.session-event-listener" value="example.VPDSessionEventAdapter" /&gt;
</pre>
<p>Include the following to provide one connection per entity manager:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;property name="eclipselink.jdbc.exclusive-connection.mode" value="Always" /&gt;
</pre>
<p>Include the following to allow native queries to be runnable from EclipseLink. This is required for creating VPD artifacts:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;property name="eclipselink.jdbc.allow-native-sql-queries" value="true" /&gt;
&lt;/properties&gt;
</pre>
<p>For example:</p>
<pre xml:space="preserve" class="oac_no_warn">
&lt;properties&gt;
&lt;property name="eclipselink.session-event-listener" value="example.VPDSessionEventAdapter" /&gt;
&lt;property name="eclipselink.jdbc.exclusive-connection.mode" value="Always" /&gt;
&lt;property name="eclipselink.jdbc.allow-native-sql-queries" value="true" /&gt;
...
&lt;/properties&gt;
</pre></div>
<!-- class="sect3" --></div>
<!-- class="sect2" --></div>
<!-- class="sect1" --></div>
<!-- class="ind" -->
<!-- Start Footer -->
<div class="footer">
<hr />
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100%">
<col width="33%" />
<col width="*" />
<col width="33%" />
<tr>
<td valign="bottom">
<table class="navigation simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="100" align="center">
<col width="*" />
<col width="48%" />
<col width="48%" />
<tr>
<td>&nbsp;</td>
<td align="center"><a href="multitenancy003.htm"><img src="../../dcommon/images/larrow.png" alt="Previous" border="0" height="16" width="16" /></a></td>
<td align="center"><a href="multitenancy005.htm"><img src="../../dcommon/images/rarrow.png" alt="Next" border="0" height="16" width="16" /></a></td>
</tr>
</table>
</td>
<td align="center" width="34%"><a href="http://www.eclipse.org/eclipselink/" title="EclipseLink home"><img src="../../dcommon/images/ellogo.png" alt="EclipseLink" width="150" border="0" /></a><br />
<font size="-2">Copyright&nbsp;&copy;&nbsp;2014,&nbsp;Oracle&nbsp;and/or&nbsp;its&nbsp;affiliates.&nbsp;All&nbsp;rights&nbsp;reserved.</font> <a href="../../dcommon/html/cpyr.htm"><br />
<td valign="bottom" align="right">
<table class="simple oac_no_warn" summary="" cellspacing="0" cellpadding="0" width="225">
<tr>
<td>&nbsp;</td>
<td align="center" valign="top"><a href="toc.htm"><img src="../../dcommon/images/contents.png" alt="Go To Table Of Contents" border="0" height="16" width="16" /><br />
</td><td>&nbsp;</td><td align="center"><a href="../../" target="_top" class="external text" title="Search" rel="nofollow"><img src="../../dcommon/images/search.png" alt="Search" style="border:0;" /><br /><span class="mini"></span></a></td><td>&nbsp;</td><td align="center"><a href="../eclipselink_otlcg.pdf" title="PDF" target="_blank"><img src="../../dcommon/images/pdf_icon.png" style="padding-right:5px;border:0" alt="PDF"></a></td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<!-- class="footer" -->
<div id="copyright">Copyright &copy; 2014 by The Eclipse Foundation under the <a href="http://www.eclipse.org/org/documents/epl-v10.php">Eclipse Public License (EPL)</a><br /> <script type="text/javascript">var LastUpdated = document.lastModified;document.writeln ("Updated: " + LastUpdated);</script> </div><!-- START: Analytics --><script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-1608008-2']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script><!-- END: Analytics --><!-- START: Sharethis --><script>var options={ "publisher": "e2fe9e07-fab6-4f84-83ea-0991b429842c", "position": "right", "ad": { "visible": false, "openDelay": 5, "closeDelay": 0}};var st_hover_widget = new sharethis.widgets.hoverbuttons(options);</script><!-- END: Sharethis --></body>
</html>