MaiPenRai - Get Started.

Just a few simple steps are required to get started using the MaiPenRai framework.

Configure the framework.

To configure the MaiPenRai framework, perform these simple steps:

  • Download and set up one of the supported databases. The feature section of the main page contains links to supported databases. Note that the databases may use a different license policy than the MaiPenRai framework.
  • Download the current MaiPenRai jar and dependent jars:
  • Create a configuration file db.properties
    • For MySQL, replace DbName with your database name. See MySQL Connector/J doc for more details.
      db.adapter.class=net.sourceforge.maipenrai.jdbc.JdbcAdapter
      jdbc.dialect=mysql
      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql:///DbName
      
    • For HSQL, replace DbName with your database name. HSQL supports several different ways to set up your database (memory only, in-process stored in a few files, standalone server). The url suggested here is for the "in-process" variant. As given here, the file is stored in the current directory. If you want a specific location, you may specify it as e.g. "C:\Databases\DbName" or "/var/opt/DbName". See HSQL doc for more details.
      db.adapter.class=net.sourceforge.maipenrai.jdbc.JdbcAdapter
      jdbc.dialect=hsql
      jdbc.driver=org.hsqldb.jdbcDriver
      jdbc.url=jdbc:hsqldb:file:DbName
      
  • Create a database with the name specified (not necessary for in-process HSQL).
  • Include the downloaded jar's in the classpath.
  • Make sure that the db.properties is located in a root directory in the classpath.

Start using the framework.

Now you may start writing domain objects that should be persisted:

  • Persistent classes should extend the net.sourceforge.maipenrai.DbObjectImpl class (or implement the net.sourceforge.maipenrai.DbObject interface).
  • Specifying Depth - all methods handling object mapping with the database use a depth specifier to indicate whether the operation should be performed on related objects or not. This includes store, retrieve, delete and search operations.
    • Depth.SHALLOW: Performs the operation on the given object only, i.e. do not follow relations. When searching for objects with this option, instances of related objects (one level) are created but not retrieved from the database.
    • Depth.DEEP: Performs the operation on the given objects and recursively on all related objects.
  • Methods provided through the DbObjectImpl class:
    • store: Stores the object in the database.
    • delete: Deletes the object from the database.
    • retrieve: Retrieve an object from the database. Note, this is not a normal search - the dbId must be known, which is usually the case when performing a search with the Depth.SHALLOW option.
    • isRetrieved and setRetrieved: Used to get or set retrieve status on the object. That is, whether it has been retrieved from the database. The framework will set the correct status.
    • isCreated and setCreated: Used to get or set created status on the object. The framework will set the correct status.
    • getDbId and setDbId: These methods are used to get or set the unique database id the the framework use to identify objects. They are used quite a lot internally, but rarely outside the framework.
    • getDbName: Returns the database name of this class, default is the same name as the class, but it can be overridden using the @Name annotation.
    • getFieldValue and setFieldValue: Methods used to get or set the field value of any field on the class. Used internally.
  • Search for objects, using the net.sourceforge.maipenrai.DbSearch class. You provide the classes to search for, condition classes (optional) and the where clause. Any number of parameters for the where-clause are supported.
    • A search for all customers with a lastname containing the substring "Haugen".
      DbSearch search = new DbSearch(Customer.class, "lastName like ?", "%Haugen%");
      Customer[] customers = (Customer[]) search.find(Depth.DEEP);
      
    • A search for any customers with the name "Steinar Haugen". Note the use of parameters for the search.
      DbSearch search = new DbSearch(Customer.class, "firstName=? and lastName=?", "Steinar", "Haugen");
      Customer[] customers = (Customer[]) search.find(Depth.DEEP);
      
    • The same Search in more than one class. Useful when searching for classes that extends a common class. Here we assume that the three classes UserCustomer, PayerCustomer and ResponsibleCustomer all extends the class Customer and that the fields firstName and lastName is provided in the super class. Note that it is not enough to search for instances of the Customer class here.
      // Set up the classes to search for
      DbClass[] searchClasses = new DbClass[]{
              new DbClass(UserCustomer.class),
              new DbClass(PayerCustomer.class)
              new DbClass(ResponsibleCustomer.class)
      };
      
      // Set up the search
      DbSearch search = new DbSearch(searchClasses, "firstName=? and lastName=?", "Steinar", "Haugen");
      
      // Set the result type, this must be a common super class for all provided classes
      // By default the array type is DbObject[] when more than one class is specified.
      search.setResultType(Customer.class);
      
      Customer[] customers = (Customer[]) search.find(Depth.DEEP);
      
    • A more complex search, using condition classes. In this search we expand further on the case above, assuming that a Customer have associations to a Country and City class. Thus, the search is for Steinar Haugen, located in Holmestrand, Norway. To make this example more clear, we provide some extracts from the domain classes.
      // Snip from the Customer class
      public class Customer extends DbObjectImpl {
          private String firstName;
          private String lastName;
          private City city;
          private Country country;
      
          // methods...
      }
      
      // Snip from the Country class
      public class Country extends DbObjectImpl {
          private String name;
      
          // methods...
      }
      
      // Snip from the City class
      public class City extends DbObjectImpl {
          private String name;
      
          // methods...
      }
      
      // ... The search ...
      
      // Set up the classes to search for, note the aliases which should
      // be the same one for all search classes.
      DbClass[] searchClasses = new DbClass[]{
              new DbClass(UserCustomer.class, "cu"),
              new DbClass(PayerCustomer.class, "cu")
              new DbClass(ResponsibleCustomer.class, "cu")
      };
      
      // Set up the classes only needed for conditions.
      // Here we must use different aliases for each class.
      DbClass conditionClasses = new DbClass[]{
              new DbClass(Country.class, "co"),
              new DbClass(City.class, "ci")
      };
      
      // Set up the search, note how associated classes are specified in the search
      DbSearch search = new DbSearch(searchClasses, conditionClasses,
              "cu.firstName=?" +
              " and cu.lastName=?" +
              " and cu.city=ci.dbId",
              " and cu.country=co.dbId" +
              " and ci.name=?" +
              " and co.name=?",
              "Steinar", "Haugen", "Holmestrand", "Norway");
      
      // Set up the result type
      search.setResultType(Customer.class);
      
      // Perform the search
      Customer[] customers = (Customer[]) search.find(Depth.DEEP);