<groupId>org.faktorips.productinfo-db</groupId>
<artifactId>productinfo-db-tool</artifactId>
<version>25.1.0</version>
Faktor-IPS Tool for Product, Enum and Table Info in Relational Databases
A tool for the creation of SQL scripts which create and fill database tables with product, enumeration and table details from a Faktor-IPS repository.
Usage
The tool is meant to be run on the command line and is configured by a JSON file.
How to get it
Download the JAR with maven:
It depends on a matching version (25.1.0.release) of the Faktor-IPS runtime. The Product data must also be created with Faktor-IPS 25.1.0.release or newer.
Command Line
To run the tool, you need Java 8 or newer. Make sure the Faktor-IPS repositories you want to export and the productinfo-db-tool.jar
are on the classpath and provide the path to the configuration file as a parameter. Several SQL files will be written in the same location as the configuration file, using the configuration file’s name and suffixes to indicate their use: “<config>_drop.sql”, “<config>_create.sql” and “<config>_insert.sql”.
java -cp "path/to/product.jar;path/to/model.jar;path/to/productinfo-db-tool.jar" \
org.faktorips.productinfodb.tool.ProductInfoSqlCreator\
path/to/productinfo.json
Maven
When using the command line tool with Maven, especially if the project uses Spring and therefore has lots of bundles on its classpath, it may be necessary to configure Maven to use a long classpath:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>generate-productinfo</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<longClasspath>true</longClasspath>(1)
<arguments>
<argument>-classpath</argument>
<classpath />(2)
<argument>org.faktorips.productinfodb.tool.ProductInfoSqlCreator</argument>
<argument>path/to/productinfo.json</argument>
</arguments>
</configuration>
</plugin>
1 | Use long classpath |
2 | Provide the Maven dependencies on the classpath |
Configuration
The configuration file uses the JSON format and contains the following keys:
-
repository
: the path to a table-of-contents file (which must be on the classpath) and optionally one or more references repositories (for example a line-of-business independent base product or model repository) -
datatypeMapping
: a mapping of Java classes to database column definitions; superclasses likejava.lang.Number
may be used to assign the same data type to all subclasses -
booleanRepresentation
: a mapping of boolean values to their representation in the database; defaults to 'TRUE'/'FALSE' if not configured -
dateFormat
: a mapping of LocalDate.class and LocalTime.class to their representation in the database; defaults to '"yyyy-MM-dd" and "HH:mm:ss" if not configured -
drop
: a template string for a database table drop statement; must contain the replacement parameter${tableName}
; aCASCADE CONSTRAINTS
or equivalent statement may be required for smooth deletion in your database -
create
: a template string for a database table create statement; must contain the replacement parameters${tableName}
and${columns}
-
insert
: a template string for a database table insert statement; must contain the replacement parameters${tableName}
and${values}
(optional; the default isINSERT INTO ${tableName} VALUES(${values});
) -
tableNames
: defines how table names are generated:-
prefixProduct
: the prefix prepended to all product tables -
prefixEnum
: the prefix prepended to all enum tables -
prefixTable
: the prefix prepended to all IPS-table tables -
maxLength
: defines the maximum table name length including the prefix, defaults to 128 characters
-
-
columnNames
: defines how column names are generated:-
maxLength
: defines the maximum column name length, defaults to 128 characters
-
-
exclude
: a list of class names of enums that should not be exported
The template strings are used to create the individual statements for each table and should be specific to the syntax of your database. |
It is also possible to include headers and/or footers for the drop/create/insert files. To do so, instead of a simple template string, a template structure containing the property statement
as well as header
and/or `footer`can be configured.
{
"repository": {
"toc": "org/faktorips/productinfodb/test/products/internal/faktorips-repository-toc.xml",
"referencedRepositories": [
{
"toc": "org/faktorips/productinfodb/test/model/internal/faktorips-repository-toc.xml"
}
]
},
"datatypeMapping": {
"java.lang.String": "VARCHAR(255)",
"java.lang.Boolean": "NUMBER(1,0)",
"boolean": "NUMBER(1,0)",
"java.lang.Number": "DECIMAL(20, 2)",
"java.lang.Integer": "INT",
"java.time.LocalDate": "DATE",
"java.time.LocalTime": "TIME",
"java.time.LocalDateTime": "TIMESTAMP"
},
"booleanRepresentation": {
"true": "1",
"false": "0"
},
"dateFormat": {
"java.time.LocalDate": "dd-MM-YYYY",
"java.time.LocalTime": "HH:mm"
},
"drop": "DROP TABLE IF EXISTS ${tableName} CASCADE CONSTRAINTS;",
"create" : {
"statement" : "CREATE TABLE ${tableName}(${columns});",
"header" : "-- header comment",
"footer" : "-- footer comment"
},
"tableNames": {
"prefixProduct": "PROD_",
"prefixEnum": "ENUM_",
"prefixTable": "TABLE_",
"maxLength": 30
},
"columnNames": {
"maxLength": 30
},
"exclude": [
"org.faktorips.productinfodb.test.model.enums.ExcludedEnum"
]
}
Annotations
The tool takes all products and table contents from the configured repository and looks for their respective product component types and table structures. If it finds an annotation @IpsProductInfoTable
on the class, a table will be created for that class. The name of the table can be given as the value of the annotation. If no name is given, a name is created from the class name, converting from CamelCase to ALL_UPPER_CASE_WITH_UNDERSCORES (ProductPart
→ PRODUCT_PART
), optionally with a prefix if configured. All subclasses of a product component type are written in the same table, unless they are themselves annotated with @IpsProductInfoTable
- only then may they add their own attributes (see below). All the table contents of an annotated table structure are written in the same table as well.
@IpsProductCmptType(name = "base.Product")
@IpsAttributes({ "intAttribute", "decimalAttribute", "dateAttribute", "timeAttribute", "dateTimeAttribute", "notMapped",
"superAttribute", "booleanAttribute", "primitiveBooleanAttribute", "superAbstractEnumAttribute",
"multiValueEnum", "multiValueString", "multiValueInteger" })
@IpsConfigures(Policy.class)
@IpsTableUsages({ "SingleContentTable" })
@IpsDocumented(bundleName = "org.faktorips.productinfodb.test.model.model-label-and-descriptions", defaultLocale = "en")
@IpsProductInfoTable(Product.TABLE_NAME)
public class Product extends AbstractProduct {
In addition, all non-abstract enum classes from the repository are also exported to separate tables. @IpsProductInfoTable
annotations can be used to specify table names but are not required for enums. To exclude specific enums from the data base, use the exclude
configuration.
For each annotated product class, one column named ID
is created for the runtime ID. For enums, the columns ID
and NAME
are created for their default identifier and display name attributes (these attributes must not be annotated with @IpsProductInfoTableColumn
and will always use these fixed column names). For table structures, a column named TABLE_CONTENT_NAME
is created to store the name of the table content.
Further columns can be defined by annotating the getter methods for product attributes/table columns with @IpsProductInfoTableColumn
. As mentioned before, the name for the column can be given as an argument to the annotation, or be derived from the attributes/columns name. Annotated attributes from superclasses are included, but it is not possible to add further attributes in subclasses (unless the subclass defines its own table).
/**
* Returns the value of intAttribute.
*
* @generated
*/
@IpsAttribute(name = "intAttribute", kind = AttributeKind.CONSTANT, valueSetKind = ValueSetKind.AllValues, primitive = true)
@IpsProductInfoTableColumn
@Generated
public int getIntAttribute() {
return intAttribute;
}
/**
* Returns the value of dateAttribute.
*
* @generated
*/
@IpsAttribute(name = "dateAttribute", kind = AttributeKind.CONSTANT, valueSetKind = ValueSetKind.AllValues)
@IpsProductInfoTableColumn("DATE")
@Generated
public LocalDate getDateAttribute() {
return dateAttribute;
}
To configure Faktor-IPS so that these annotations are retained when the code generator runs, add them to the "Retain annotations" code generator property: <Property name="retainAnnotations" value="IpsProductInfoTable;IpsProductInfoTableColumn"/>
|
Enums as Product Attributes
For attributes or columns that specify an enum as type, a foreign key constraint will be automatically created on the product component type table or table structure table. The prerequisite for this is that the attribute or column is annotated as @IpsProductInfoTableColumn
and both classes are annotated as @IpsProductInfoTable
. This allows for efficient join operations.
SELECT * FROM PRODUCTS LEFT JOIN ENUMS ON PRODUCTS.ENUM_ATTRIBUTE=ENUMS.ID;
API
The ProductInfoDbConfig
also provides a constructor using a predetermined IRuntimeRepository
. You can use this to integrate the ProductInfoSqlCreator
into your own tools or pipeline.
public ProductInfoDbConfig(IRuntimeRepository repository,
Map<Class<?>, String> datatypeMapping, Function<Boolean, String> booleanRepresentation,
Map<Class<?>, String> dateFormat,
Template dropStatementTemplate, Template createStatementTemplate, Template insertStatementTemplate,
TableNameConfig tableNames, ColumnNameConfig columnNames, List<EnumType> excludedEnums) {