JavaXT ORM - Object Relational Mapping
The javaxt-orm library is a handy tool for generating Java code and DDL from a set of models defined in a Javascript or JSON document. The generated classes are used to persist data in a relational database via the javaxt.sql.Model class.
Download javaxt-orm
Current Version: 1.2.3
Release Date: 10/9/2024
File Size: 53 KB
File Format: Zip
Includes: Jar File and Source Code
Key Features
- Auto-generate database schema and Java classes
- Command line interface
- Supports spatial geometry types with JTS
- Plug and play with javaxt-core and javaxt-express
- Supports common RDMBS (PostgreSQL, H2, etc)
Note that this is not intended to be a full fledged ORM framework. Instead, the goal is to help jumpstart new projects by providing a simple utility for stubbing out code and SQL.
Basic Usage
The javaxt-orm library provides a command line interface that can be used to generate Java classes and schema. All you need to do is provide a input model and an output directory. Example:
java -jar javaxt-orm.jar /path/to/model.js /output
After you run the script, the output directory will contain a "schema.sql" and *.java files with source code.
Example Model
Below is a simple example of a file in Javascript format with an Address model.
var package = "com.example.models";
var models = {
Address: {
fields: [
{name: 'street', type: 'string'},
{name: 'city', type: 'string'},
{name: 'state', type: 'string'},
{name: 'postalCode', type: 'string'},
{name: 'coordinates', type: 'geo'}
]
}
}
In the above example, there are 2 variables:
- package: Name of the Java package that will contain the source code.
- models: JSON with model specs.
Model Specs
Individual models are defined using one or more fields. In addition, models can have constraints and default values, as well as other settings. Here's a full list of all the parameters.
- fields: An array of field names and field type. Models must contain at least 1 field. The full range of supported field types is listed below.
- constraints: An array of database constraints for individual fields. This parameter is optional.
- defaults: An array of default values for individual fields. This parameter is optional.
- hasMany: An array of Model names. This parameter is optional.
- implements: An array of Java classes that the model implements (e.g. java.security.Principal). This parameter is optional.
Supported Field Types
| Field Type | Java Type | Database Type | Comments |
|---|---|---|---|
| int | Integer | integer | |
| int[] | Integer[] | integer array | |
| long | Long | bigint | |
| float | Double | double precision | |
| double | Double | double precision | |
| decimal | BigDecimal | numeric | |
| numeric | BigDecimal | numeric | |
| text | String | varchar | |
| text[] | String[] | varchar array | |
| string | String | varchar | |
| string[] | String[] | varchar array | |
| char | String | char(1) | |
| boolean | Boolean | Boolean | |
| date | Date | timestamp with time zone | Java class maps to javaxt.utils.Date |
| binary | byte[] | bytea | |
| json | JSONObject | jasonb | Java class maps to javaxt.json.JSONObject |
| geo | Geometry | geometry(Geometry,4326) | For lat/lon geographic data. Java class maps to org.locationtech.jts.geom.Geometry. |
| geometry | Geometry | geometry(GeometryZ) | For x,y,z data. Java class maps to org.locationtech.jts.geom.Geometry. |
| password | String | text | Stores bcrypt hash in the database (vs plaintext password) |
Notes:
- IDs are automatically added so you don't have to explicitly define one in the model.
- lastUpdate fields in the model are automatically assigned a trigger in the database.
Model Field Type
In addition to the standard field types, you can specify another model as a `type`. In the example below, the address field in the Contact model is a `Address` type.
{
Contact: {
fields: [
{name: 'name', type: 'string'},
{name: 'address', type: 'Address'}
]
},
Address: {
...
}
}
When a model is used as a type, a foreign key is created in the database.
Supported Field Constraints
| Constraint Key | Type | Comments |
|---|---|---|
| required | boolean | If true, adds a "NOT NULL" constraint to the field. Can also use "nullable" keyword. |
| length | int | Only applies to "text" field types. Reassigns the database type to varchar. |
| unique | boolean | If true, adds a "UNIQUE" constraint to the field. Should NOT be applied to "text" fields without a length constraint. |
| onDelete | string | Only applies to fields with models. Options include "cascade" and "no action" (default). |
Field Defaults
Individual fields can be assigned a default value using the "defaults" array. Each entry in the array should include:
- name: Name of the field.
- value: Default value (e.g. number, text, or boolean).
Example Model With Constraints and Defaults
The following is an example of a "User" model with constraints defined for several fields (e.g. username, password, active):
{
User: {
fields: [
{name: 'username', type: 'string'},
{name: 'password', type: 'password'},
{name: 'accessLevel', type: 'int'},
{name: 'active', type: 'boolean'},
{name: 'contact', type: 'Contact'},
{name: 'auth', type: 'json'}
],
constraints: [
{field: 'username', required: true, length: 255, unique: true},
{field: 'password', required: true},
{field: 'active', required: true}
],
defaults: [
{name: 'active', value: true}
]
}
}
You can also define constraints in the field definitions like this:
{
User: {
fields: [
{name: 'username', type: 'string', required: true, length: 255, unique: true},
{name: 'password', type: 'password', required: true},
{name: 'accessLevel', type: 'int'},
{name: 'active', type: 'boolean', required: true},
{name: 'contact', type: 'Contact'},
{name: 'auth', type: 'json'}
]
}
}
Indexes
Indexes are created automatically for any foreign keys associated with models and any "geo: field type. You can add additional indexes using the "indexes" array like this:
{
Contact: {
fields: [
{name: 'firstName', type: 'string'},
{name: 'lastName', type: 'string'},
{name: 'birthDay', type: 'int'},
{name: 'address', type: 'Address'} //see address model example
],
indexes: [
{field: 'firstName'},
{field: 'lastName'},
{field: 'address'}
]
}
}
You can simplify the index definitions further like this:
{
Contact: {
fields: [
...
],
indexes: [ 'firstName','lastName','address' ]
}
}
Or you can create more complex indexes like this:
{
Contact: {
fields: [
...
],
indexes: [
{name: 'idx_contact_name', type: 'unique', field: ['firstName','lastName']},
{name: 'idx_contact_address', field: 'address'}
]
}
}
Advanced Options
In addition to the "package" and "model" variables, there are a few optional variables:
- tablespace: Name of the tablespace to use for the database object (tables, indexes, etc).
- jts: Which JTS package to use when using geometry types. Options are "org.locationtech.jts" and "com.vividsolutions.jts"
Dependencies
The javaxt-orm library is compiled using Java 11 requires the following libraries:
- Nashorn for parsing model inputs in Javascript format
- javaxt-core for JSON and basic file I/O
Generated Code Dependencies
The javaxt-orm library generates Java code that extends/implements javaxt.sql.Model class. It also calls java.util.Map.ofEntries which was introduced in Java 9. Therefore, you will need both javaxt-core and Java 9 (or higher) to use the generated code in your project. In addition, you will need JTS if you include a `geo` or `geometry` type. Last but not least, you will need to include a JDBC driver in your project for persistance.
License
All JavaXT libraries are free and open source released under a permissive MIT license. This software comes with no guarantees or warranties. You may use this software in any open source or commercial project.
Maven Support
If you're a Maven user, you can configure your pom.xml to pull releases directly from this site. To add javaxt-orm to your project, simply add this site to your list of repositories and add a dependency. XML snippits below. See the downloads page for more information.
<repositories>
<repository>
<id>javaxt.com</id>
<url>https://www.javaxt.com/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>javaxt</groupId>
<artifactId>javaxt-orm</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>