Easy database queries for Java

Mini-ORM Overview (Deprecated)

Jinq currently uses a mini-ORM (object-relational mapper) to build object representations of the various tables and fields in your database. To use Jinq with your data, you must first use this mini-ORM to describe your database to Jinq.

Overview

This is the general process for using the mini-ORM:

  1. Use XML to describe your database schema and how it should be mapped to Java
  2. Use the mini-ORM to generate Java objects from your XML file
  3. Use the generated objects in your code

XML Description of Database

The Jinq mini-ORM requires an XML description of the tables of a SQL database and how it should be mapped to Java objects. The mini-ORM currently supports a basic mapping where tables are mapped to classes and where relationships are described with foreign keys. Inheritance relationships are not supported.

A simple mini-ORM XML file looks like this:

<?xml version="1.0"?>
<entities package="com.example.orm.entities">
   <jdbc driver="org.apache.derby.jdbc.EmbeddedDriver"
      db="jdbc:derby:demoDB"/>

   <entity name="Customer" table="Customers">
      <field name="CustomerId" type="int" column="CustomerId" 
	     key="true"/>
      <field name="Name" type="String" column="Name"/>
   </entity>

   <link map="1:N">
      <from entity="Customer" field="Purchases"/>
      <to entity="Sale" field="Purchaser"/>
      <column from="CustomerId" to="CustomerId"/>
   </link>

   <entity name="Sale" table="Sales">
      <field name="SaleId" type="int" column="SaleId" 
	     key="true"/>
      <field name="Date" type="Date" column="Date"/>
   </entity>
</entities>	

The XML file starts with the standard XML header, and then an <entities> root element. This element has an attribute @package, which lists the Java package that should be used to hold the generated Java objects used to represent database entities.

jdbc element

Jinq currently uses JDBC to read data from SQL databases. The configuration information needed to start JDBC is supplied in the <jdbc> element. The element must describe which JDBC driver to use, and the location of the database.

entity element

The <entity> element is used to tell Jinq about the existence of a SQL database table. These tables are mapped 1:1 to a class. Each row of the table becomes an object instance of that class.

For example, consider the code below.

<?xml version="1.0"?>
<entities package="com.example.orm.entities">

   <entity name="Customer" table="Customers">
      <field name="CustomerId" type="int" column="CustomerId" 
	     key="true"/>
      <field name="Name" type="String" column="Name"/>
   </entity>
   
</entities>

In this case, the XML file describes a SQL table called Customers (taken from the @table attribute). The mini-ORM will create a class called Customer (based on the info provided in the @name attribute) in the package com.example.orm.entities.

Inside the <entity> element are various <field> elements. These elements are used to describe the various columns of the database table. These are then mapped to member variables of the generated class. The mini-ORM also generates setters and getters for accessing these member variables.

The <field> element has the following attributes:

link element

The <link> element is used to describe the various relationships between tables. The mini-ORM generates navigational links between objects using this information. Three types of links are supported: 1:1, 1:N, and N:M.

<link map="1:1">
   <from entity="Customer" field="Account"/>
   <to entity="Account" field="Customer"/>
   <column from="CustomerId" to="CustomerId"/>
</link>

The 1:1 link is used to describe a relationship where one object is always related to one of another object. For example, in the above code, every Customer has an Account (and vice versa). The <from> and <to> elements use the @entity attributes to say which two objects are linked together. The @field attributes are used to create getter methods. In the above example, the Customer object will have a getAccount() getter method for getting the corresponding account for a customer. Finally, the <from> element is used to say how to map a foreign key column from the from-table to the primary key column of the to-table.

<link map="1:N">
   <from entity="Customer" field="Purchases"/>
   <to entity="Sale" field="Purchaser"/>
   <column from="CustomerId" to="CustomerId"/>
</link>

The 1:N link is used to describe relationships where one object can have many related objects. For example, a customer might make many purchases. Each purchase is only made by one customer, however. These links are described in the same way 1:1 links. The only difference is that the getter method on the from object will return a set of to objects instead of a single object.

The mini-ORM also supports N:1 mappings.

<link map="N:M">
   <from entity="Item" field="Suppliers"/>
   <to entity="Supplier" field="Supplies"/>
   <column from="ItemId" tableto="ItemId" table="ItemSuppliers"/>
   <column tablefrom="SupplierId" to="SupplierId" table="ItemSuppliers"/>
</link>

The N:M links are used to describe more arbitrary relationships. The above code describes a relationship where items can have many different suppliers and suppliers can supply many different items. Like 1:N and 1:1 links, there are <from> and <to> elements. The <column> elements are more complicated though. Unlike the other types of links, N:M links require a third database table. This table holds two foreign keys: one foreign key maps to the primary key of the from-table, and the other foreign key maps to the primary key of the to-table. The above example shows how this is denoted in the XML.

Generate Java Objects

Once you have an XML file describing your database schema, you can use the mini-ORM to generate your corresponding Java classes. Basically, you run the program ch.epfl.labos.iu.orm.tools.EntityGenerator and supply two arguments: the XML file describing your database, and a directory where the generated files should be outputted to. The Jinq build.xml file contains an example in the demo for how to do this.

Use the Generated Objects

Afterwards, you can then use the generated objects in your code.