Dashboard > RIFE > ... > Database > Creating tables
RIFE Log In | Sign Up   View a printable version of the current page.
Creating tables


Added by Steven Grimm, last edited by Steven Grimm on Jul 18, 2006  (view change) show comment
Labels: 
(None)

RIFE can create tables programmatically in a database-independent way (including foreign key specifications and other constraints). There are two approaches depending on whether your tables map to RIFE-managed beans or are self-managed.

Automated table creation using RIFE constraints

If your table is simply the persistent form of a RIFE-managed bean, you can use RIFE's constraint mechanism to create the table for you. Your constraints need to specify the column metadata for each field in addition to any other constraints needed by your elements:

ProductReview.java
package com.foo;

public class ProductReview {
    public static final int MAX_REVIEW_LENGTH = 300;
    private int id;
    private int userId;
    private int productId;
    private String review;
    private float score;

    public int getId() { return this.id; }
    ... and other getters and setters ...
}
ProductReviewMetaData.java
package com.foo;

import com.uwyn.rife.config.RifeConfig;
import com.uwyn.rife.site.ConstrainedProperty;
import com.uwyn.rife.site.MetaData;

public class ProductReviewMetaData extends MetaData {
    public void activateMetaData()
    {
	addConstraint(new ConstrainedProperty("id")
				.identifier(true)
				.editable(false));
	addConstraint(new ConstrainedProperty("userId")
				.notNull(true)
				.manyToOne(User.class, "id"));
	addConstraint(new ConstrainedProperty("productId")
				.notNull(true)
				.manyToOne(Product.class, "id"));
	addConstraint(new ConstrainedProperty("review")
				.notNull(true)
				.notEmpty(true)
				.maxLength(ProductReview.MAX_REVIEW_LENGTH));
	addConstraint(new ConstrainedProperty("score")
				.notNull(true)
				.rangeBegin(0)
				.rangeEnd(10));
    }
}

Then you can call an instance of GenericQueryManager to instantiate the bean's table. One approach is to centralize all your table creation in a single element that gets called when the site starts up. RIFE's Deployer class is useful here. If an element's getDeploymentClass() method returns a subclass of Deployer, that class will be instantiated and its deploy() method will be called during RIFE's initialization.

DatabaseDeployer.java
package com.foo;

import java.util.logging.Logger;

import com.uwyn.rife.authentication.credentialsmanagers.DatabaseUsersFactory;
import com.uwyn.rife.authentication.exceptions.*;
import com.uwyn.rife.authentication.remembermanagers.DatabaseRememberFactory;
import com.uwyn.rife.authentication.sessionmanagers.DatabaseSessionsFactory;
import com.uwyn.rife.cmf.dam.ContentQueryManager;
import com.uwyn.rife.cmf.dam.contentmanagers.DatabaseContentFactory;
import com.uwyn.rife.cmf.dam.exceptions.ContentManagerException;
import com.uwyn.rife.config.RifeConfig;
import com.uwyn.rife.database.Datasource;
import com.uwyn.rife.database.exceptions.DatabaseException;
import com.uwyn.rife.engine.Element;
import com.uwyn.rife.engine.ElementDeployer;

/**
 * Initialization element that creates database tables. This is only
 * useful in a development environment; in production we will of course
 * want to hand-create all our tables to tune their storage parameters.
 */
public class DatabaseDeployer extends Element
{
    @Override
    public Class getDeploymentClass() {
	return Deployer.class;
    }
	
    public static class Deployer extends ElementDeployer
    {
	private Logger log = Logger.getLogger(Deployer.class.getName());
	private Datasource ds = null;

	/**
	 * Installs the database tables for a class that has RIFE constraints.
	 * 
	 * @return true if the table was actually installed, false if it
	 * 		already existed.
	 */
	private boolean install(Class clazz)
	{
	    ContentQueryManager mgr = new ContentQueryManager(ds, clazz);
	    try {
		mgr.install();
		return true;
	    }
	    catch (DatabaseException e) {
		log.fine(e.getMessage());
		return false;
	    }
	}

	public void deploy()
	{
            // Pull your datasource from the repository
	    ds = (Datasource) getElementInfo().getProperty("datasource");

            // If you're using the content management framework, set up its
            // tables like this.
	    try {
		DatabaseContentFactory.getInstance(ds).install();
	    } catch (ContentManagerException e) {
		log.fine(e.getMessage());
	    }

            // If you're using database users, create the user tables.
	    try {
		DatabaseUsersFactory.getInstance(ds).install();
            }
	    catch (CredentialsManagerException e) {
		log.fine(e.getMessage());
	    }

            // If you're using database sessions, create the session tables.
	    try {
		DatabaseSessionsFactory.getInstance(ds).install();
	    } catch (DatabaseException e) {
		log.fine(e.getMessage());
	    } catch (SessionManagerException e) {
		log.fine(e.getMessage());
	    }

            // If you're using "remember me", create the remember key table.
	    try {
		DatabaseRememberFactory.getInstance(ds).install();
	    } catch (DatabaseException e) {
		log.fine(e.getMessage());
	    } catch (RememberManagerException e) {
		log.fine(e.getMessage());
	    }

            // Now install the tables for each of your constrained beans.
	    install(Account.class);
	    install(Product.class);
	    install(ProductReview.class);
	    install(ShoppingCart.class);
	}
    }
}

This element does not actually serve any pages, so it should be included in your site participants file a with no URL:

<element id="DatabaseDeployer" implementation="com.foo.DatabaseDeployer" />

Manual table creation using CreateTable

If your table is not associated with a RIFE-managed bean, you can still take advantage of RIFE's database independence by constructing your table creation query with RIFE's CreateTable object. Here we will create a simple join table for a many-to-many relationship. CreateTable has lots of additional methods for precisely specifying column types, nullability, etc.

Manual table creation
CreateTable ct = new CreateTable(dataSource);
DbQueryManager qm = new DbQueryManager(dataSource);

ct.table("subscription")
  .column("magazineid", int.class)
  .column("customerid", int.class)
  .primaryKey(new String[] { "magazineid", "customerid" })
  .foreignKey("customer", "customerid", "id")
  .foreignKey("magazine", "magazineid", "id");

try {
    qm.executeUpdate(ct);
}
catch (DatabaseException e) {
    // This can happen if the table already exists! So don't
    // bomb out here.
}



Are you enjoying Confluence? Please consider purchasing it today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.1a Build:#515 May 19, 2006) - Bug/feature request - Contact Administrators