Java ACDP Tutorial

Creation

In Chapter Design we coded the classes for a sample database. Once the classes have been coded, creating the actual database is just a matter of running a single method of the Setup Tool. But before that, a few preparatory work needs to be done.

The remaining sections of this page are

Preparing the Classes

For the setup tool to run successfully, the database class and the table classes must meet a few requirements. It is worth noting that these requirements only need to be met during the one-time process of creating the database, which means that all changes made for this purpose can be undone afterwards. Such changes are highlighted below.

Preparing the Database Class

The following things must be done: Here is the annotated sample database class from Chapter Design:
   @SetupDatabase(
      name = "Edu",
      tables = { "Course", "Student", "Teacher", "Contact" }
   )
   final class EduDB extends CustomDatabase {
      @SetupTableDeclaration("Course")
      static final CourseTable COURSE_TABLE = new CourseTable();
      @SetupTableDeclaration("Student")
      static final StudentTable STUDENT_TABLE = new StudentTable();
      @SetupTableDeclaration("Teacher")
      static final TeacherTable TEACHER_TABLE = new TeacherTable();
      @SetupTableDeclaration("Contact")
      static final ContactTable CONTACT_TABLE = new ContactTable();
   
      EduDB(Path mainFile, int opMode, boolean writeProtect,
                                                      int consistencyNumber) {
         open(mainFile, opMode, writeProtect, null, consistencyNumber,
                   COURSE_TABLE, STUDENT_TABLE, TEACHER_TABLE, CONTACT_TABLE);
      }
   }
Remarks:
  1. The name of the database is specified as the value of the name element of the @SetupDatabase annotation. Besides the required name and tables elements, the @SetupDatabase annotation has an optional version element which we haven't used in this example.
  2. The name of a table is specified with the @SetupTableDeclaration annotation. The table names are repeated in the tables element of the @SetupDatabase annotation.
  3. The order of the table names listed in the tables element of the @SetupDatabase annotation must be the same as the order in which the corresponding table variables appear in the open method. (The open method is invoked in the constructor.)

Preparing the Table Classes

The following things must be done:
  • The class declaration must include the public access level modifier and be annotated with the @SetupTable annotation.
  • Each column declaration must include the public access level modifier and must be annotated with the @SetupColumn annotation.
  • The table class must have a public no-arg constructor.
As an example, here the annotated Student table class from Chapter Design:
   @SetupTable({ "Student Number", "Name", "Contact", "Courses" })
   public final class StudentTable extends CustomTable {
      @SetupColumn("Student Number")
      public static final Column<Integer> STUDENT_NUMBER = CL.ofInteger(NO_NULL);
      @SetupColumn("Name")
      public static final Column<String> NAME = CL.ofString(NO_NULL, SMALL);
      @SetupColumn(value = "Contact", refdTable = "Contact")
      public static final Column<Ref> CONTACT = CL.ofRef();
      @SetupColumn(value = "Courses", refdTable = "Course")
      public static final Column<Ref[]> COURSES = CL.ofArrayOfRef(30);
      
      public StudentTable() {
         initialize(STUDENT_NUMBER, NAME, CONTACT, COURSES);
      }
   }
Remarks:
  1. The name of a column is specified with the @SetupColumn annotation. The column names are repeated in the @SetupTable annotation.
  2. The order of the column names listed in the @SetupTable annotation must be the same as the order in which the corresponding column variables appear in the initialize method. (The initialize method is invoked in the constructor.)
  3. The name of the referenced table of a column with a reference type is specified by the refdTable element of the @SetupColumn annotation. Recall that the name of a table is specified as the value of the @SetupTableDeclaration annotation used in the database class.

Creating the Database

Invoking Setup.run(String, Path) creates the database. The first parameter specifies the qualified name of the database class and the second the directory where to save the generated database files. (The database class is the class annotated with the @SetupDatabase annotation.)

For example, we create our sample database and save it to the dbDir directory by executing

   Setup.run("example.db.EduDB", Paths.get("dbDir"));
If nothing goes wrong a message similar to
   INFO: Database "Edu" successfully created and saved to "dbDir".
is printed to the standard output stream.

Among the files created in the dbDir directory you'll find a file with the name layout. The layout file is the main database file of a WR database and contains all information needed to run the database. (The WR database type is explained in the next section.) You can open the layout file with any text viewer and read it. The entries are formatted as described in the Layout class. Do you recognize the name of the database, the names of its tables and the names of the tables' columns we just specified in the previous section? Section Changing Settings of Chapter Maintenance shows you how to safely change the entries in the layout file.

Note: Never change the layout file manually, unless you are a real ACDP expert!

Creating an RO Database from a WR Database

When we speak of an ACDP database we usually mean the writable WR type. However, there is a second database type, the RO type. An RO database is readonly and resides in a highly compacted single file. As will be shown in Chapter Opening, an RO database can be loaded completely into main memory, provided that enough main memory is available. An application whose data is completely in main memory usually scales better with respect to the number of concurrent read operations compared to an application that has to read data on demand from a secondary memory device.

An RO database stored in a file specified by the first argument of the following method can be created from an open WR database by invoking the

   createRO(Path, ICipherFactory)
method from either an instance of a custom database class (a custom database class inherits this method from the CustomDatabase class) or of an instance implementing the Database interface, depending on whether the database was opened as a strongly or weakly typed database, respectively. (In Chapter Opening you learn how to open a database as a strongly typed or a weakly typed database.)

Specifying a non-null value for the ICipherFactory parameter results in an encrypted RO database.

Note that the reverse way, that is the creation of a WR database from an RO database, is not possible.
Back To Top