{"id":17858605,"url":"https://github.com/vzakharchenko/dynamic-orm","last_synced_at":"2025-07-27T22:33:00.090Z","repository":{"id":40364625,"uuid":"244584201","full_name":"vzakharchenko/dynamic-orm","owner":"vzakharchenko","description":"Querying and Managing data on runtime","archived":false,"fork":false,"pushed_at":"2024-10-22T01:15:35.000Z","size":672,"stargazers_count":20,"open_issues_count":37,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-23T00:48:27.900Z","etag":null,"topics":["annotation","crud-operation","database","dynamic","dynamic-sql","dynamic-structures","liquibase","orm","orm-framework","querydsl","transaction-manager"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vzakharchenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-03T08:43:00.000Z","updated_at":"2024-09-25T06:14:37.000Z","dependencies_parsed_at":"2023-09-25T06:46:10.445Z","dependency_job_id":"d71f88ea-897e-43c1-a503-c576b2760b10","html_url":"https://github.com/vzakharchenko/dynamic-orm","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzakharchenko%2Fdynamic-orm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzakharchenko%2Fdynamic-orm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzakharchenko%2Fdynamic-orm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzakharchenko%2Fdynamic-orm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vzakharchenko","download_url":"https://codeload.github.com/vzakharchenko/dynamic-orm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227732304,"owners_count":17811362,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation","crud-operation","database","dynamic","dynamic-sql","dynamic-structures","liquibase","orm","orm-framework","querydsl","transaction-manager"],"created_at":"2024-10-28T05:22:24.043Z","updated_at":"2024-12-03T03:02:48.304Z","avatar_url":"https://github.com/vzakharchenko.png","language":"Java","readme":"# Dynamic Orm\n[![CircleCI](https://circleci.com/gh/vzakharchenko/dynamic-orm.svg?style=svg)](https://circleci.com/gh/vzakharchenko/dynamic-orm)  \n![Java CI with Maven](https://github.com/vzakharchenko/dynamic-orm/workflows/Java%20CI%20with%20Maven/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/vzakharchenko/dynamic-orm/badge.svg?branch=master)](https://coveralls.io/github/vzakharchenko/dynamic-orm?branch=master)  \n[![Maintainability](https://api.codeclimate.com/v1/badges/5c587a6e77be5e8cbef0/maintainability)](https://codeclimate.com/github/vzakharchenko/dynamic-orm/maintainability)  \n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.vzakharchenko/dynamic-orm/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.vzakharchenko/dynamic-orm)  \n[![BCH compliance](https://bettercodehub.com/edge/badge/vzakharchenko/dynamic-orm?branch=master)](https://bettercodehub.com/)  \n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7bd6c5b0ce2e4ca9ae497aff44a8a64a)](https://www.codacy.com/manual/vzaharchenko/dynamic-orm?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=vzakharchenko/dynamic-orm\u0026amp;utm_campaign=Badge_Grade)  \n[![Known Vulnerabilities](https://snyk.io/test/github/vzakharchenko/dynamic-orm/badge.svg)](https://snyk.io/test/github/vzakharchenko/dynamic-orm)  \n[![donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://secure.wayforpay.com/button/b8de34ba8b4ab)   \n\n# supported database\n - Oracle\n - Postgres\n - MySQL\n - MariaDB\n - Hsql\n - H2\n - Derby\n - Firebird\n - SQLite\n - MSSQL\n - DB2\n# Features\n  - modify database structure on runtime (use Liquibase)\n    - create tables\n    - add/modify columns\n    - add/remove indexes\n    - add/remove foreign keys\n    - etc...\n  - crud operation on dynamic structures\n    - insert\n    - update\n    - delete (soft delete)\n    - support optimistic locking (Version column)\n  - quering to dynamic structures\n    - select\n    - CTE\n    - subqueries\n    - union\n    - join\n  - cache operation\n    - based on spring cache\n    - Transaction and External(ehcache, infinispan, redis, etc) cache\n    - cache queries based on Primary Key, Column, and Column and Values\n    - synchronization cache with crud operations\n  - support clustering( if use distributed cache)\n  - support create Sql sequence on runtime\n  - support create/update View on runtime\n  - save/load dynamic structure\n  - support Composite Primary key\n\n# dependencies\n - [querydsl](http://www.querydsl.com/) - crud operation(insert, update, delete),  querying (select, union, CTE)\n - [Spring transaction manager](https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html) - transaction manager\n - [Spring cache abstraction](https://docs.spring.io/spring-framework/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/cache.html) - Cache abstraction\n - [Liquibase](https://www.liquibase.org/get_started/index.html) - support dynamic structure\n - [Spring  beans](https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html) - ioc container to connect all parts together\n# Installation\n##  1. Maven\n```xml\n \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.github.vzakharchenko\u003c/groupId\u003e\n            \u003cartifactId\u003edynamic-orm-core\u003c/artifactId\u003e\n            \u003cversion\u003e1.3.1\u003c/version\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n```\n## 2. Spring Xml or Annotation\n\n```xml\n     \u003c!-- transaction Manager --\u003e\n    \u003cbean id=\"transactionManager\" class=\"com.github.vzakharchenko.dynamic.orm.core.transaction.TransactionNameManager\"\u003e\n        \u003cproperty name=\"dataSource\" ref=\"dataSource\"/\u003e\n        \u003cproperty name=\"validateExistingTransaction\" value=\"true\"/\u003e\n    \u003c/bean\u003e\n    \u003c!-- enable support annotation  --\u003e\n    \u003ctx:annotation-driven transaction-manager=\"transactionManager\"/\u003e\n\n    \u003cbean id=\"sharedTransactionTemplate\" class=\"org.springframework.transaction.support.TransactionTemplate\"\u003e\n        \u003cconstructor-arg name=\"transactionManager\" ref=\"transactionManager\"/\u003e\n        \u003cproperty name=\"isolationLevelName\" value=\"ISOLATION_READ_COMMITTED\"/\u003e\n        \u003cproperty name=\"timeout\" value=\"30000\"/\u003e\n    \u003c/bean\u003e\n\n\n    \u003cbean name=\"springOrmQueryFactory\" class=\"com.github.vzakharchenko.dynamic.orm.core.SpringOrmQueryFactory\"\u003e\n        \u003cproperty name=\"dataSource\" ref=\"dataSource\"/\u003e\n        \u003cproperty name=\"transactionCacheManager\" ref=\"transaction-cache\"/\u003e\n        \u003cproperty name=\"transactionalEventPublisher\" ref=\"transaction-publisher\"/\u003e\n        \u003cproperty name=\"transactionManager\" ref=\"transactionManager\"/\u003e\n    \u003c/bean\u003e\n    \n    \u003c!-- The main factory for building queries and data modification --\u003e\n    \u003cbean name=\"ormQueryFactory\" factory-bean=\"springOrmQueryFactory\" factory-method=\"getInstance\"/\u003e\n\n    \u003c!-- Dynamic database supporting --\u003e\n    \u003cbean class=\"com.github.vzakharchenko.dynamic.orm.core.dynamic.QDynamicTableFactoryImpl\"\u003e\n        \u003cconstructor-arg ref=\"dataSource\"/\u003e\n    \u003c/bean\u003e\n\n    \u003c!-- Transaction Event Manager--\u003e\n    \u003cbean id=\"transaction-publisher\"\n          class=\"com.github.vzakharchenko.dynamic.orm.core.transaction.event.TransactionAwareApplicationEventPublisher\"/\u003e\n          \n              \u003c!-- Datasource - factory for connections to the physical data source --\u003e\n    \u003cbean id=\"dataSource\" class=\"javax.sql.DataSource\"\n          ... /\u003e\n    \u003c/bean\u003e\n    \u003c!-- Spring Cache Abstraction Manager. You can use ehcache, Infinispan, Redis and etc... --\u003e\n    \u003cbean id=\"cacheManager\" class=\"org.springframework.cache.concurrent.ConcurrentMapCacheManager\"/\u003e\n\n    \u003cbean id=\"transaction-cache\"\n          class=\"com.github.vzakharchenko.dynamic.orm.core.transaction.cache.TransactionCacheManagerImpl\"\u003e\n        \u003cconstructor-arg name=\"targetCacheManager\" ref=\"cacheManager\"/\u003e\n    \u003c/bean\u003e\n```\nOr You can use Annotation:\n```java\n@Configuration\n@EnableTransactionManagement\n@EnableCaching\npublic class SpringAnnotationTest extends CachingConfigurerSupport {\n    private TransactionNameManager transactionNameManager = new TransactionNameManager();\n    private DbStructureServiceImpl dbStructureService = new DbStructureServiceImpl();\n    TransactionAwareApplicationEventPublisher transactionAwareApplicationEventPublisher =\n            new TransactionAwareApplicationEventPublisher();\n\n    @Bean\n    public PlatformTransactionManager annotationDrivenTransactionManager() {\n        transactionNameManager.setDataSource(dataSource());\n        transactionNameManager.setValidateExistingTransaction(true);\n        return transactionNameManager;\n    }\n\n    @Bean\n    public DataSource dataSource() {\n        try {\n            return DataSourceHelper.getDataSourceHsqldbCreateSchema(\"jdbc:hsqldb:mem:DATABASE_MYSQL;sql.mys=true\");\n        } catch (Exception e) {\n            throw new IllegalStateException(e);\n        }\n    }\n\n    @Bean\n    public TransactionTemplate sharedTransactionTemplate() {\n        TransactionTemplate transactionTemplate = new TransactionTemplate();\n        transactionTemplate.setTransactionManager(transactionNameManager);\n        transactionTemplate.setTimeout(3000);\n        transactionTemplate.setIsolationLevel(ISOLATION_READ_COMMITTED);\n        return transactionTemplate;\n    }\n\n    @Bean\n    public DbStructureService staticStructure() {\n        dbStructureService.setDataSource(dataSource());\n        dbStructureService.setPathToChangeSets(\"classpath:/changeSets/\");\n        return dbStructureService;\n    }\n\n    @Bean()\n    public OrmQueryFactory ormQueryFactory() {\n                 OrmQueryFactoryInit.create(dataSource())\n                .transactionCacheManager(new TransactionCacheManagerImpl(cacheManager()))\n                .transactionalEventPublisher(transactionAwareApplicationEventPublisher) // event publisher\n                .debug() // show all sql queries in logger\n                .cacheRegion(\"cache-orm\") // cache region\n                .transactionManager(transactionNameManager)\n                .build();\n    }\n\n    @Bean\n    @Override\n    public CacheManager cacheManager() {\n        return new ConcurrentMapCacheManager();\n    }\n\n    @Bean\n    public TransactionalEventPublisher transactionalEventPublisher() {\n        return transactionAwareApplicationEventPublisher;\n    }\n}\n```\n\n## 3. Example to Use\n - autowire factories\n```java\n    @Autowired\n    private OrmQueryFactory ormQueryFactory;\n\n    @Autowired\n    private QDynamicTableFactory qDynamicTableFactory;\n```\n - add @Transactional annotation, or use transaction Manager\n```java\n    @Transactional()\n    public void testQuery() {\n     ...\n    }\n```\n or\n```java\n    public void testQuery() {\n               TransactionBuilder transactionManager = ormQueryFactory.transactionManager();\n        transactionManager.startTransactionIfNeeded();\n        ...\n        transactionManager.commit();\n    }\n```\n - create schema example\n```java\n@Transactional()\npublic void testQuery() {\n            qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addStringColumn(\"Id\")\n                .size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"TestStringColumn\").size(255).createColumn()\n                .addDateColumn(\"modificationTime\").createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(UUIDPKGenerator.getInstance())\n                .endPrimaryKey()\n                .addVersionColumn(\"modificationTime\")\n                .endBuildTables().buildSchema();\n}\n```\n - load dynamic structure from current connection\n```java\n        qDynamicTableFactory.loadCurrentSchema();\n```\n\n - save dynamic structure to file\n```java\n        File file = new File(\".\", \"testSchema.json\");\n        qDynamicTableFactory.saveSchema(SchemaUtils.getFileSaver(file));\n```\n - load dynamic structure from file\n```java\n        File file = new File(\".\", \"testSchema.json\");\n        qDynamicTableFactory.loadSchema(SchemaUtils.getFileLoader(file));\n```\n - get  table metadata\n```java\n QDynamicTable firstTable = qDynamicTableFactory.getQDynamicTableByName(\"firstTable\");\n```\n   - insert operation\n```java\n        DynamicTableModel firstTableModel1 = new DynamicTableModel(firstTable);\n        firstTableModel1.addColumnValue(\"TestStringColumn\", \"testValue\");\n        ormQueryFactory.insert(firstTableModel1);\n```\n   - modify table metadata\n```java\n  // add integer column to table\n        qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addNumberColumn(\"newColumn\", Integer.class).createColumn().endColumns()\n                .endBuildTables().buildSchema();\n```\n - add custom column type\n```java\n        qDynamicTableFactory.buildTables(\"dynamicTestTable\")\n                .columns()\n                    .addCustomColumn(\"customColumn\")\n                    .column(Expressions::stringPath)\n                    .jdbcType(new NVarcharType())\n                    .createColumn()\n                .endColumns()\n                .endBuildTables().buildSchema();\n```\n - update operation\n```java\n        firstTableModel1.addColumnValue(\"newColumn\", 122);\n        ormQueryFactory.updateById(firstTableModel1);\n```\n   - fetch data\n```java\n        DynamicTableModel firstTableFromDatabase = ormQueryFactory.select().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n```\n   - fetch data with Wildcard\n```java\n        StringPath testColumn = dynamicTable.getStringColumnByName(\"TestColumn\");\n\n        // fetch all data from all table\n        // if you want cache the result you can use selectCache() instead of select() \n        List\u003cRawModel\u003e rawModels = ormQueryFactory.select().rawSelect(\n                ormQueryFactory.buildQuery().from(dynamicTable)\n                        .orderBy(testColumn.asc())).findAll(Wildcard.all);\n        \n        RawModel rawModel = rawModels.get(0);\n        Object columnValue1 = rawModel.getValueByPosition(0);\n        Object columnValue2 = rawModel.getValueByPosition(1);\n        Object columnValue3 = rawModel.getValueByPosition(2);\n```\n\n   - fetch data and put result to the cache. Cache record will be evicted if any related table is modified (insert/update/delete operartion)\n```java\n        DynamicTableModel firstTableFromDatabase = ormQueryFactory.selectCache().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n```\nhow it works:\n```java\n        // fetch data and put result to cache\n        DynamicTableModel firstTableFromDatabase = ormQueryFactory.selectCache().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n\n        // fetch result from the cache\n        firstTableFromDatabase = ormQueryFactory.selectCache().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n        \n        // any \"firstTable\" modification will evict the query result from the cache \n        ormQueryFactory.insert(new DynamicTableModel(firstTable));\n        \n        // fetch data and put result to the cache\n        DynamicTableModel firstTableFromDatabase = ormQueryFactory.selectCache().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n```\n - limit and offset\n```java\n    ormQueryFactory.selectCache().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable).limit(3).offset(3)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n```\n\n  - get column value from model\n```java\n               String testStringColumnValue = firstTableFromDatabase.getValue(\"TestStringColumn\", String.class);\n```\n  - join queries\n```java\n        // fetch data (if you want cache the result you can use selectCache() instead of select() )\n        List\u003cRawModel\u003e rawModels = ormQueryFactory.select().rawSelect(\n                ormQueryFactory.buildQuery().from(firstTable)\n                        .innerJoin(secondTable).on(\n                        secondTable.getStringColumnByName(\"linkToFirstTable\").eq(\n                                firstTable.getStringColumnByName(\"Id\")))\n                        .where(secondTable.getBooleanColumnByName(\"isDeleted\").eq(false)))\n                .findAll(ArrayUtils.addAll(firstTable.all(), secondTable.all()));\n        RawModel rawModel = rawModels.get(0);\n        DynamicTableModel firstModelFromJoin = rawModel.getDynamicModel(firstTable);\n        DynamicTableModel secondModelFromJoin = rawModel.getDynamicModel(secondTable);\n```\n\n[Full Example](dynamic-orm-core/src/test/java/com/github/vzakharchenko/dynamic/orm/core/QueryAnnotationTest.java#L20-L126):\n\n```java\n\n    @Autowired\n    private OrmQueryFactory ormQueryFactory;\n\n    @Autowired\n    private QDynamicTableFactory qDynamicTableFactory;\n    \n // suspend the current transaction if one exists.\n    @Transactional(propagation = Propagation.NOT_SUPPORTED)\n    public void testQuery() {\n         TransactionBuilder transactionManager = ormQueryFactory.transactionManager();\n        transactionManager.startTransactionIfNeeded();\n        // build schema\n        qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addStringColumn(\"Id\")\n                .size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"TestStringColumn\").size(255).createColumn()\n                .addDateColumn(\"modificationTime\").createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(UUIDPKGenerator.getInstance())\n                .endPrimaryKey()\n                .addVersionColumn(\"modificationTime\")\n                .buildNextTable(\"secondTable\")\n                .columns().addStringColumn(\"Id\")\n                .size(255).useAsPrimaryKey().createColumn()\n                .addBooleanColumn(\"isDeleted\").notNull().createColumn()\n                .addDateTimeColumn(\"modificationTime\").notNull().createColumn()\n                .addStringColumn(\"linkToFirstTable\").size(255).createColumn()\n                .addStringColumn(\"uniqValue\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(UUIDPKGenerator.getInstance()).endPrimaryKey()\n                .addSoftDeleteColumn(\"isDeleted\", true, false)\n                .addVersionColumn(\"modificationTime\")\n                .index(\"uniqValue\").addUniqueIndex()\n                .foreignKey(\"linkToFirstTable\").addForeignKey((\"firstTable\")\n                .endBuildTables().buildSchema();\n        transactionManager.commit();\n\n        QDynamicTable firstTable = qDynamicTableFactory.getQDynamicTableByName(\"firstTable\");\n        QDynamicTable secondTable = qDynamicTableFactory.getQDynamicTableByName(\"secondTable\");\n\n        // insert data to the first table\n        transactionManager.startTransactionIfNeeded();\n        DynamicTableModel firstTableModel1 = new DynamicTableModel(firstTable);\n        firstTableModel1.addColumnValue(\"TestStringColumn\", \"testValue\");\n        ormQueryFactory.insert(firstTableModel1);\n\n        // insert data to the second table\n        DynamicTableModel secondModel1 = new DynamicTableModel(secondTable);\n        secondModel1.addColumnValue(\"uniqValue\", \"123\");\n        secondModel1.addColumnValue(\"linkToFirstTable\", firstTableModel1.getValue(\"Id\"));\n\n        DynamicTableModel secondModel2 = new DynamicTableModel(secondTable);\n        secondModel2.addColumnValue(\"uniqValue\", \"1234\");\n        secondModel2.addColumnValue(\"linkToFirstTable\", firstTableModel1.getValue(\"Id\"));\n\n        ormQueryFactory.insert(secondModel1, secondModel2);\n        transactionManager.commit();\n\n\n        // add integer column to table1\n        transactionManager.startTransactionIfNeeded();\n        qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addNumberColumn(\"newColumn\", Integer.class).createColumn().endColumns()\n                .endBuildTables().buildSchema();\n        transactionManager.commit();\n\n\n        // modify first table\n        transactionManager.startTransactionIfNeeded();\n        firstTableModel1.addColumnValue(\"newColumn\", 122);\n        ormQueryFactory.updateById(firstTableModel1);\n\n        // select one value from firstTable where newColumn == 122\n        DynamicTableModel firstTableFromDatabase = ormQueryFactory.select().findOne(ormQueryFactory\n                        .buildQuery()\n                        .from(firstTable)\n                        .where(firstTable.getNumberColumnByName(\"newColumn\").eq(122)),\n                firstTable,\n                DynamicTableModel.class);\n        // get value of TestStringColumn from firstTable\n        String testStringColumnValue = firstTableFromDatabase.getValue(\"TestStringColumn\", String.class);\n        assertEquals(testStringColumnValue, \"testValue\");\n\n        // get value  from secondTable and put it to cache\n        List\u003cDynamicTableModel\u003e tableModels = ormQueryFactory.selectCache().findAll(secondTable);\n        assertEquals(tableModels.size(), 2);\n        transactionManager.commit();\n\n        // get value from cache\n        ormQueryFactory.selectCache().findAll(secondTable);\n\n        //soft delete the second row of the second Table\n        transactionManager.startTransactionIfNeeded();\n        ormQueryFactory.softDeleteById(secondModel2);\n        transactionManager.commit();\n\n        // get new cache records (soft deleted values are not included)\n        tableModels = ormQueryFactory.selectCache().findAll(secondTable);\n        assertEquals(tableModels.size(), 1);\n\n        // fetch all data from all table\n        // if you want cache the result you can use selectCache() instead of select() \n        List\u003cRawModel\u003e rawModels = ormQueryFactory.select().rawSelect(\n                ormQueryFactory.buildQuery().from(firstTable)\n                        .innerJoin(secondTable).on(\n                        secondTable.getStringColumnByName(\"linkToFirstTable\").eq(\n                                firstTable.getStringColumnByName(\"Id\")))\n                        .where(secondTable.getBooleanColumnByName(\"isDeleted\").eq(false)))\n                .findAll(ArrayUtils.addAll(firstTable.all(), secondTable.all()));\n\n        assertEquals(rawModels.size(), 1);\n        RawModel rawModel = rawModels.get(0);\n        DynamicTableModel firstModelFromJoin = rawModel.getDynamicModel(firstTable);\n        DynamicTableModel secondModelFromJoin = rawModel.getDynamicModel(secondTable);\n        assertEquals(firstModelFromJoin.getValue(\"Id\"), firstTableFromDatabase.getValue(\"Id\"));\n        assertEquals(secondModelFromJoin.getValue(\"Id\"), secondModel1.getValue(\"Id\"));\n    }\n```\n# SQL INDEX\n## create index on runtime\n```java\n        qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addStringColumn(\"Id\")\n                .size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"column1\").size(255).createColumn()\n                .addStringColumn(\"column2\").size(255).createColumn()\n                .endColumns()\n                .index(\"column1\",\"column2\").addIndex()\n                .endBuildTables().buildSchema();\n```\n\n## create unique index on runtime\n```java\n        qDynamicTableFactory.buildTables(\"firstTable\")\n                .columns().addStringColumn(\"Id\")\n                .size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"column1\").size(255).createColumn()\n                .addStringColumn(\"column2\").size(255).createColumn()\n                .endColumns()\n                .index(\"column1\",\"column2\").clustered().addUniqueIndex()\n                .endBuildTables().buildSchema();\n```\n\n## drop index on runtime\n```java\n  // create schema\n        qDynamicTableFactory.buildTables(\"table1\").columns()\n                .addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"column1\").size(255).createColumn()\n                .addStringColumn(\"column2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .index(\"column1\", \"column2\").addIndex()\n                .endBuildTables().buildSchema();\n\n        // drop Index\n        qDynamicTableFactory.buildTables(\"table1\")\n                .index(\"column1\", \"column2\").drop()\n                .endBuildTables().buildSchema();\n        \n```\n# Foreign Key\n## create foreign key on runtime\n```java\nqDynamicTableFactory.buildTables(\"table1\").columns()\n                .addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .buildNextTable(\"table2\")\n                .columns()\n                .addStringColumn(\"Id2\").size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"Id1\").size(255).notNull().createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .foreignKey(\"Id1\").addForeignKey(\"table1\")\n                .endBuildTables().buildSchema();\n```\n## drop foreign key on runtime\n ```java\n    // create table1 and table2\n  qDynamicTableFactory.buildTables(\"table1\").columns()\n                .addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .buildNextTable(\"table2\")\n                .columns()\n                .addStringColumn(\"Id2\").size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"Id1\").size(255).notNull().createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .foreignKey(\"Id1\").addForeignKey(\"table1\")\n                .endBuildTables().buildSchema();\n        QDynamicTable table1 = qDynamicTableFactory.getQDynamicTableByName(\"table1\");\n        QDynamicTable table2 = qDynamicTableFactory.getQDynamicTableByName(\"table2\");\n\n        // insert Table 1\n        DynamicTableModel dynamicTableModel1 = new DynamicTableModel(table1);\n        ormQueryFactory.insert(dynamicTableModel1);\n\n        // insert to table 2 with foreign Key\n        DynamicTableModel dynamicTableModel2 = new DynamicTableModel(table2);\n        dynamicTableModel2.addColumnValue(\"id1\", dynamicTableModel1.getValue(\"Id1\"));\n        ormQueryFactory.insert(dynamicTableModel2);\n\n        // drop foreign Key\n\n        qDynamicTableFactory.buildTables(\"table2\")\n                .foreignKey(\"Id1\").drop()\n                .endBuildTables().buildSchema();\n\n\n        // insert to table 2 with foreign Key\n        DynamicTableModel dynamicTableModel2WithoutForeign = new DynamicTableModel(table2);\n        dynamicTableModel2WithoutForeign.addColumnValue(\"id1\", \"Not Foreign Key Value\");\n        ormQueryFactory.insert(dynamicTableModel2WithoutForeign);\n```\n# Static Tables(not Dynamic)\n## - QueryDsl Models (Table Metadata)\n```java\n@Generated(\"com.querydsl.query.sql.codegen.MetaDataSerializer\")\npublic class QTestTableVersionAnnotation extends RelationalPathBase\u003cQTestTableVersionAnnotation\u003e {\n\n    public static final QTestTableVersionAnnotation qTestTableVersionAnnotation = new QTestTableVersionAnnotation(\"TEST_TABLE_VERSION_ANNOTATION\");\n\n    public final NumberPath\u003cInteger\u003e id = createNumber(\"id\", Integer.class);\n\n    public final NumberPath\u003cInteger\u003e version = createNumber(\"version\", Integer.class);\n\n    public final PrimaryKey\u003cQTestTableVersionAnnotation\u003e idPk = createPrimaryKey(id);\n\n    public QTestTableVersionAnnotation(String variable) {\n        super(QTestTableVersionAnnotation.class, forVariable(variable), \"\", \"TEST_TABLE_VERSION_ANNOTATION\");\n        addMetadata();\n    }\n\n    public QTestTableVersionAnnotation(String variable, String schema, String table) {\n        super(QTestTableVersionAnnotation.class, forVariable(variable), schema, table);\n        addMetadata();\n    }\n\n    public QTestTableVersionAnnotation(Path\u003c? extends QTestTableVersionAnnotation\u003e path) {\n        super(path.getType(), path.getMetadata(), \"\", \"TEST_TABLE_VERSION_ANNOTATION\");\n        addMetadata();\n    }\n\n    public QTestTableVersionAnnotation(PathMetadata metadata) {\n        super(QTestTableVersionAnnotation.class, metadata, \"\", \"TEST_TABLE_VERSION_ANNOTATION\");\n        addMetadata();\n    }\n\n    public void addMetadata() {\n        addMetadata(id, ColumnMetadata.named(\"ID\").withIndex(1).ofType(Types.INTEGER).withSize(38).notNull());\n        addMetadata(version, ColumnMetadata.named(\"VERSION\").withIndex(2).ofType(Types.INTEGER).withSize(38).notNull());\n    }\n\n}\n```\n## - Static POJO Model\n```java\n@QueryDslModel(qTableClass = QTestTableVersionAnnotation.class, tableName = \"TEST_TABLE_VERSION_ANNOTATION\", primaryKeyGenerator = PrimaryKeyGenerators.SEQUENCE)\n@SequanceName(\"TEST_SEQUENCE\")\npublic class TestTableVersionAnnotation implements DMLModel {\n\n    private Integer id;\n    @Version\n    private Integer version;\n\n    public Integer getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    public Integer getVersion() {\n        return version;\n    }\n\n    public void setVersion(Integer version) {\n        this.version = version;\n    }\n}\n```\nAnnotations:\n- **@QueryDslModel** - related QueryDsl model.\n  -  qTableClass - queryDsl class\n  -  tableName - Table name\n  -  primaryKeyGenerator - Primary Key generator\n     -  DEFAULT - does not use PK generator\n     -  INTEGER - integer values\n     -  LONG - long values\n     -  UUID - Universally Unique Identifier values (UUID.randomUUID().toString())\n     -  SEQUENCE - Sql Sequence (if database support)\n- **@SequanceName** - Sequance annotation\n- **@Version** - mark field as Optimistic locking. (Supports only TimeStamp and numeric column)\n\n## Example of Usage\n\n - insert\n```java\n        TestTableVersionAnnotation testTableVersion = new TestTableVersionAnnotation();\n        ormQueryFactory.insert(testTableVersion);\n```\n - update\n```java\n        testTableVersion.setSomeColumn(\"testColumn\")\n        ormQueryFactory.updateById(testTableVersion);\n```\n - select Version column and put result to cache\n```java\n        Integer version = ormQueryFactory.selectCache().findOne(\n                ormQueryFactory.buildQuery()\n                        .from(QTestTableVersionAnnotation.qTestTableVersionAnnotation)\n                        .where(QTestTableVersionAnnotation.qTestTableVersionAnnotation.id.eq(testTableVersion.getId()))\n                , QTestTableVersionAnnotation.qTestTableVersionAnnotation.version);\n```\n - join with dynamic table\n```java\n        TestTableVersionAnnotation staticTable = new TestTableVersionAnnotation();\n        ormQueryFactory.insert(staticTable);\n        // build dynamic Table with foreign Key to Static Table\n        qDynamicTableFactory.buildTables(\"relatedTable\")\n                .columns().addStringColumn(\"Id\").size(255).useAsPrimaryKey().createColumn()\n                .addNumberColumn(\"StaticId\", Integer.class).createColumn()\n                .addDateTimeColumn(\"modificationTime\").notNull().createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(UUIDPKGenerator.getInstance()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime\")\n                .foreignKey(\"StaticId\").addForeignKey((QTestTableVersionAnnotation.qTestTableVersionAnnotation,  QTestTableVersionAnnotation.qTestTableVersionAnnotation.id)\n                .endBuildTables().buildSchema();\n\n        // fetch dynamic table metadata\n        QDynamicTable relatedTable = qDynamicTableFactory.getQDynamicTableByName(\"relatedTable\");\n\n        // insert to dynamic table\n        DynamicTableModel relatedTableData = new DynamicTableModel(relatedTable);\n        relatedTableData.addColumnValue(\"StaticId\", staticTable.getId());\n\n        ormQueryFactory.insert(relatedTableData);\n\n        // fetch with join\n         // if you want cache the result you can use selectCache() instead of select()\n        DynamicTableModel tableModel = ormQueryFactory\n                .select()\n                .findOne(ormQueryFactory\n                                .buildQuery().from(relatedTable)\n                                .innerJoin(QTestTableVersionAnnotation.qTestTableVersionAnnotation)\n                                .on(relatedTable\n                                        .getNumberColumnByName(\"StaticId\", Integer.class)\n                                        .eq(QTestTableVersionAnnotation\n                                                .qTestTableVersionAnnotation.id))\n                                .where(QTestTableVersionAnnotation\n                                        .qTestTableVersionAnnotation.id.eq(staticTable.getId())),\n                        relatedTable);\n        assertNotNull(tableModel);\n        assertEquals(tableModel.getValue(\"Id\"), relatedTableData.getValue(\"Id\"));\n```\n\n - drop column\n```java\n        qDynamicTableFactory.buildTables(\"DynamicTable\")\n                .columns()\n                    .dropColumns(\"TestColumn\")\n                .endColumns()\n                .endBuildTables().buildSchema();\n```\n - modify column\n```java\n        qDynamicTableFactory.buildTables(\"DynamicTable\")\n                .columns()\n                    .modifyColumn()\n                    .size(\"TestColumn\", 1)\n                    .finish()\n                .endColumns()\n                .endBuildTables()\n                .buildSchema();\n```\n - drop table or View\n```java\n        qDynamicTableFactory\n                .dropTableOrView(\"TABLE_OR_VIEW_NAME\").buildSchema();\n```\n - drop Sequence\n```java\n        qDynamicTableFactory\n                .dropSequence(\"sequence_name\").buildSchema();\n```\n## Generate QueryDslModel\n[Example](dynamic-orm-examples/example-test-qmodels/pom.xml)\n\npom.xml\n```xml\n            \u003cplugin\u003e\n                \u003cgroupId\u003ecom.querydsl\u003c/groupId\u003e\n                \u003cartifactId\u003equerydsl-maven-plugin\u003c/artifactId\u003e\n                \u003cversion\u003e${querydsl}\u003c/version\u003e\n\n                \u003cexecutions\u003e\n                    \u003cexecution\u003e\n                        \u003cphase\u003egenerate-sources\u003c/phase\u003e\n                        \u003cgoals\u003e\n                            \u003cgoal\u003eexport\u003c/goal\u003e\n                        \u003c/goals\u003e\n                    \u003c/execution\u003e\n                \u003c/executions\u003e\n                \u003cconfiguration\u003e\n                    \u003cjdbcDriver\u003e${driver}\u003c/jdbcDriver\u003e\n                    \u003cbeanPrefix\u003eQ\u003c/beanPrefix\u003e\n                    \u003cpackageName\u003e${QmodelPackage}\u003c/packageName\u003e\n                    \u003ctargetFolder\u003e${targetFolder}\u003c/targetFolder\u003e\n                    \u003cjdbcUrl\u003e${jdbcUrl}\u003c/jdbcUrl\u003e\n                    \u003cjdbcPassword\u003e${jdbcPassword}\u003c/jdbcPassword\u003e\n                    \u003cjdbcUser\u003e${jdbcUser}\u003c/jdbcUser\u003e\n                    \u003csourceFolder /\u003e\n                \u003c/configuration\u003e\n            \u003c/plugin\u003e\n```\n\n## Generate Static POJO Models\n[Example](dynamic-orm-examples/example-test-models/pom.xml)\n\npom.xml\n\n```xml\n    \u003cbuild\u003e\n        \u003cplugins\u003e\n            \u003cplugin\u003e\n                \u003cgroupId\u003ecom.github.vzakharchenko\u003c/groupId\u003e\n                \u003cartifactId\u003edynamic-orm-plugin\u003c/artifactId\u003e\n                \u003cversion\u003e1.3.1\u003c/version\u003e\n                \u003cconfiguration\u003e\n                    \u003ctargetQModelFolder\u003e${targetFolder}\u003c/targetQModelFolder\u003e\n                    \u003cmodelPackage\u003e${ModelPackage}\u003c/modelPackage\u003e\n                    \u003cqmodelPackage\u003equeryDsl package name\u003c/qmodelPackage\u003e\n                \u003c/configuration\u003e\n                \u003cexecutions\u003e\n                    \u003cexecution\u003e\n                        \u003cphase\u003eprocess-sources\u003c/phase\u003e\n                        \u003cgoals\u003e\n                            \u003cgoal\u003emodelGenerator\u003c/goal\u003e\n                        \u003c/goals\u003e\n                    \u003c/execution\u003e\n                \u003c/executions\u003e\n            \u003c/plugin\u003e\n        \u003c/plugins\u003e\n    \u003c/build\u003e\n```\n\n# Audit database changes\n[Example: Logging Audit](dynamic-orm-examples/example-test-ehcache/src/main/java/orm/query/examples/ehcache/LogAudit.java)\n```java\n@Component\npublic class LogAudit implements ApplicationListener\u003cCacheEvent\u003e {\n    @Override\n    public void onApplicationEvent(CacheEvent cacheEvent) {\n        switch (cacheEvent.cacheEventType()) {\n            case INSERT: {\n                for (Serializable pk : cacheEvent.getListIds()) {\n                    System.out.println(\"insert table \" + cacheEvent.getQTable().getTableName()\n                            + \" primarykey = \" + pk);\n                    DiffColumnModel diffModel = cacheEvent.getDiffModel(pk);\n                    for (Map.Entry\u003cPath\u003c?\u003e, DiffColumn\u003c?\u003e\u003e entry : diffModel.getDiffModels().entrySet()) {\n                        System.out.println(\" --- column \" + ModelHelper.getColumnRealName(entry.getKey())\n                                + \" set \" + entry.getValue().getNewValue());\n                    }\n                }\n                break;\n            }\n            case UPDATE: {\n                for (Serializable pk : cacheEvent.getListIds()) {\n                    System.out.println(\"update table \" + cacheEvent.getQTable().getTableName());\n                    DiffColumnModel diffModel = cacheEvent.getDiffModel(pk);\n                    for (Map.Entry\u003cPath\u003c?\u003e, DiffColumn\u003c?\u003e\u003e entry : diffModel.getOnlyChangedColumns().entrySet()) {\n                        System.out.println(\" --- column \" + ModelHelper.getColumnRealName(entry.getKey())\n                                + \" set \" + entry.getValue().getNewValue()\n                                + \" old value \"\n                                + entry.getValue().getOldValue());\n                    }\n                }\n\n                break;\n            }\n            case SOFT_DELETE:\n            case DELETE: {\n                System.out.println(\"delete into table \" + cacheEvent.getQTable().getTableName() + \" ids = \" + ToStringBuilder.reflectionToString(cacheEvent.getListIds(), ToStringStyle.JSON_STYLE));\n                break;\n            }\n            case BATCH: {\n                List\u003c? extends CacheEvent\u003e transactionHistory = cacheEvent.getTransactionHistory();\n                for (CacheEvent event : transactionHistory) {\n                    onApplicationEvent(event);\n                }\n                break;\n            }\n            default: {\n                throw new IllegalStateException(cacheEvent.cacheEventType() + \" is not supported\");\n            }\n        }\n    }\n}\n```\n# Create Dynamic Table With Sequence Primary Key Generator\n```java\n        qDynamicTableFactory.\n                .createSequence(\"dynamicTestTableSequance1\")\n                .initialValue(1000L)\n                .increment(10L)\n                .min(1000L)\n                .max(10000L)\n                .addSequence()\n                .buildSchema();\n```\n\n# Create SQL Sequence on runtime\n```java\n        qDynamicTableFactory.buildTables(\"dynamicTestTable\")\n                .columns().addNumberColumn(\"ID\", Integer.class).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"testColumn\").size(100).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(new PKGeneratorSequence(\"dynamicTestTableSequance1\")).endPrimaryKey()\n                .endBuildTables()\n                .createSequence(\"dynamicTestTableSequance1\")\n                .initialValue(1000L)\n                .addSequence()\n                .buildSchema();\n```\n# Create SQL View on runtime\n```java\n        qDynamicTableFactory\n                .createView(\"testView\").resultSet(ormQueryFactory.buildQuery()\n                .from(QTestTableVersionAnnotation.qTestTableVersionAnnotation), QTestTableVersionAnnotation.qTestTableVersionAnnotation.id)\n                .addView()\n                .buildSchema();\n```\n# use SQL View\nif you use selectcache() pay attention to the method \"registerRelatedTables\"\n```java\n        qDynamicTableFactory\n                .createView(\"testView\").resultSet(ormQueryFactory.buildQuery()\n                .from(QTestTableVersionAnnotation.qTestTableVersionAnnotation), QTestTableVersionAnnotation.qTestTableVersionAnnotation.id).addView()\n                .buildSchema();\n\n        QDynamicTable testView = qDynamicTableFactory.getQDynamicTableByName(\"testView\");\n        assertNotNull(testView);\n\n        TestTableVersionAnnotation testTableVersionAnnotation = new TestTableVersionAnnotation();\n        ormQueryFactory.insert(testTableVersionAnnotation);\n\n        // fetch data from table\n         // if you want cache the result you can use selectCache() instead of select()\n        TestTableVersionAnnotation versionAnnotation = ormQueryFactory.select()\n                .findOne(ormQueryFactory.buildQuery(), TestTableVersionAnnotation.class);\n        assertNotNull(versionAnnotation);\n        \n        // fetch data from View\n        DynamicTableModel dynamicTableModel = ormQueryFactory.select()\n                .findOne(ormQueryFactory.buildQuery().from(testView), testView);\n        assertNotNull(dynamicTableModel);\n        \n          // fetch data from View with cache (need manually register related tables with query)\n        DynamicTableModel dynamicTableModel2 = ormQueryFactory.selectCache().registerRelatedTables(\n                Collections.singletonList(QTestTableVersionAnnotation.qTestTableVersionAnnotation))\n                .findOne(ormQueryFactory.buildQuery().from(testView), testView);\n        assertNotNull(dynamicTableModel2);\n```\n\n\n# SQL subquery (SQL query nested inside a larger query.)\n\n```java\n        // create database schema\n        qDynamicTableFactory.buildTables(\"UnionTable1\")\n                .columns().addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime1\").notNull().createColumn()\n                .addStringColumn(\"TestColumn1_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn1_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime1\")\n                .buildNextTable(\"UnionTable2\")\n                .columns()\n                .addStringColumn(\"Id2\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime2\").notNull().createColumn()\n                .addStringColumn(\"TestColumn2_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn2_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime2\")\n                .endBuildTables()\n                .buildSchema();\n\n        // get unionTable1 Metadata \n        QDynamicTable unionTable1 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable1\");\n        // get unionTable2 Metadata \n        QDynamicTable unionTable2 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable2\");\n\n        // get column from unionTable1 \n        StringPath testColumn11 = unionTable1.getStringColumnByName(\"TestColumn1_1\");\n        // get columns from unionTable2 \n        StringPath testColumn21 = unionTable2.getStringColumnByName(\"TestColumn2_1\");\n        StringPath testColumn22 = unionTable2.getStringColumnByName(\"TestColumn2_2\");\n\n        // create subquery\n        SQLQuery\u003cString\u003e query = SQLExpressions\n                .select(testColumn21)\n                .from(unionTable2).where(testColumn22.eq(\"data2\"));\n\n         // show the final SQL\n        String sql = ormQueryFactory.select().showSql(ormQueryFactory.buildQuery().from(unionTable1)\n                .where(testColumn11.in(query)), unionTable1);\n\n        assertEquals(sql, \"select \\\"UNIONTABLE1\\\".\\\"ID1\\\", \\\"UNIONTABLE1\\\".\\\"MODIFICATIONTIME1\\\", \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_1\\\", \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_2\\\"\\n\" +\n                \"from \\\"UNIONTABLE1\\\" \\\"UNIONTABLE1\\\"\\n\" +\n                \"where \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_1\\\" in (select \\\"UNIONTABLE2\\\".\\\"TESTCOLUMN2_1\\\"\\n\" +\n                \"from \\\"UNIONTABLE2\\\" \\\"UNIONTABLE2\\\"\\n\" +\n                \"where \\\"UNIONTABLE2\\\".\\\"TESTCOLUMN2_2\\\" = 'data2')\");\n\n        // fetch data\n         // if you want cache the result you can use selectCache() instead of select()\n        DynamicTableModel tableModel = ormQueryFactory.select().findOne(\n                ormQueryFactory.buildQuery().from(unionTable1)\n                        .where(testColumn11.in(query)), unionTable1);\n```\n\n# Union query with groupBy, orderBy, offset and limit\n\n```java\n        // create database schema\n        qDynamicTableFactory.buildTables(\"UnionTable1\")\n                .columns().addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime1\").notNull().createColumn()\n                .addStringColumn(\"TestColumn1_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn1_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime1\")\n                .buildNextTable(\"UnionTable2\")\n                .columns()\n                .addStringColumn(\"Id2\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime2\").notNull().createColumn()\n                .addStringColumn(\"TestColumn2_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn2_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime2\")\n                .endBuildTables()\n                .buildSchema();\n\n        // get unionTable1 Metadata\n        QDynamicTable unionTable1 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable1\");\n        // get unionTable2 Metadata\n        QDynamicTable unionTable2 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable2\");\n        \n        // get column from unionTable1\n        StringPath testColumn11 = unionTable1.getStringColumnByName(\"TestColumn1_1\");\n        StringPath testColumn12 = unionTable1.getStringColumnByName(\"TestColumn1_2\");\n        StringPath testColumn21 = unionTable2.getStringColumnByName(\"TestColumn2_1\");\n        StringPath testColumn22 = unionTable2.getStringColumnByName(\"TestColumn2_2\");\n\n        // first subquery\n        SQLQuery\u003cTuple\u003e query1 = SQLExpressions\n                .select(testColumn11.as(\"column1\"), testColumn12.as(\"column2\"))\n                .from(unionTable1).where(testColumn12.eq(\"data1\"));\n        \n        // second subquery\n        SQLQuery\u003cTuple\u003e query2 = SQLExpressions\n                .select(testColumn21.as(\"column1\"), testColumn22.as(\"column2\"))\n                .from(unionTable2).where(testColumn22.eq(\"data2\"));\n\n        // create UnionBuilder\n         // if you want cache the result you can use selectCache() instead of select()\n        UnionBuilder unionBuilder = ormQueryFactory.select()\n                .unionAll(ormQueryFactory.buildQuery(), query1, query2);\n        \n        // result order by\n        unionBuilder\n                .orderBy(\"column1\").desc().orderBy(\"column2\").asc();\n        \n        // offset and limit (offset = 0, limit = 2 )\n        unionBuilder.limit(new Range(0, 2));\n        \n        // group by result\n        unionBuilder.groupBy(\"column1\", \"column2\");\n        \n         // show final SQL\n        String sql = unionBuilder.showSql();\n        \n        assertEquals(sql, \"select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                \"from ((select \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_1\\\" as \\\"column1\\\", \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_2\\\" as \\\"column2\\\"\\n\" +\n                \"from \\\"UNIONTABLE1\\\" \\\"UNIONTABLE1\\\"\\n\" +\n                \"where \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_2\\\" = 'data1')\\n\" +\n                \"union all\\n\" +\n                \"(select \\\"UNIONTABLE2\\\".\\\"TESTCOLUMN2_1\\\" as \\\"column1\\\", \\\"UNIONTABLE2\\\".\\\"TESTCOLUMN2_2\\\" as \\\"column2\\\"\\n\" +\n                \"from \\\"UNIONTABLE2\\\" \\\"UNIONTABLE2\\\"\\n\" +\n                \"where \\\"UNIONTABLE2\\\".\\\"TESTCOLUMN2_2\\\" = 'data2')) as \\\"union\\\"\\n\" +\n                \"group by \\\"column1\\\", \\\"column2\\\"\\n\" +\n                \"order by \\\"column1\\\" desc, \\\"column2\\\" asc\\n\" +\n                \"limit 2\\n\" +\n                \"offset 0\");\n\n        // fetch result\n        List\u003cRawModel\u003e rawModels = unionBuilder.findAll();\n        \n        // get first record\n        RawModel rawModel = rawModels.get(0);\n        \n        // get column1 value\n        String column1Value = rawModel.getValueByColumnName(\"column1\", String.class);\n        \n        // get column2 value\n        String column2Value = rawModel.getValueByColumnName(\"column2\", String.class);\n\n```\n# Union count query with cache\n\n```java\n        // create database schema\n        qDynamicTableFactory.buildTables(\"UnionTable1\")\n                .columns().addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime1\").notNull().createColumn()\n                .addStringColumn(\"TestColumn1_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn1_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime1\")\n                .buildNextTable(\"UnionTable2\")\n                .columns()\n                .addStringColumn(\"Id2\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime2\").notNull().createColumn()\n                .addStringColumn(\"TestColumn2_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn2_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime2\")\n                .endBuildTables()\n                .buildSchema();\n\n       // get unionTable1 Metadata\n        QDynamicTable unionTable1 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable1\");\n        // get unionTable2 Metadata\n        QDynamicTable unionTable2 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable2\");\n        // get column from unionTable1\n        StringPath id1 = unionTable1.getStringColumnByName(\"Id1\");\n        // get column from unionTable2\n        StringPath id2 = unionTable2.getStringColumnByName(\"Id2\");\n\n\n        SQLQuery\u003cString\u003e query1 = SQLExpressions\n                .select(id1)\n                .from(unionTable1);\n\n        SQLQuery\u003cString\u003e query2 = SQLExpressions\n                .select(id2)\n                .from(unionTable2);\n\n        // create UnionBuilder\n        UnionBuilder unionBuilder = ormQueryFactory.selectCache()\n                .unionAll(ormQueryFactory.buildQuery(), query1, query2);\n\n        // unionBuilder.groupBy(\"column1\", \"column2\");\n\n         // show final SQL\n        String sql = unionBuilder.showCountSql();\n        assertEquals(sql, \"select count(*)\\n\" +\n                \"from ((select \\\"UNIONTABLE1\\\".\\\"ID1\\\"\\n\" +\n                \"from \\\"UNIONTABLE1\\\" \\\"UNIONTABLE1\\\")\\n\" +\n                \"union all\\n\" +\n                \"(select \\\"UNIONTABLE2\\\".\\\"ID2\\\"\\n\" +\n                \"from \\\"UNIONTABLE2\\\" \\\"UNIONTABLE2\\\")) as \\\"union\\\"\");\n\n        // fetch result\n        Long count1 = unionBuilder.count();\n        // result from cache\n        Long count2 = unionBuilder.count();\n        // insert to unionTable1\n        insert2(\"someData\", \"data3\"); //   ormQueryFactory.insert(unionTable2);\n        // cache is evicted and get a new value\n        Long count3 = unionBuilder.count();\n```\n#  CTE with Union query\n\n```java\n        // create database schema\n        qDynamicTableFactory.buildTables(\"UnionTable1\")\n                .columns().addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime1\").notNull().createColumn()\n                .addStringColumn(\"TestColumn1_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn1_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime1)\n                .endBuildTables()\n                .buildSchema();\n\n        // get unionTable1 Metadata\n        QDynamicTable unionTable1 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable1\");\n        // get column from unionTable1\n        StringPath testColumn11 = unionTable1.getStringColumnByName(\"TestColumn1_1\");\n        StringPath testColumn12 = unionTable1.getStringColumnByName(\"TestColumn1_2\");\n\n        SimplePath\u003cString\u003e column1 = Expressions.simplePath(String.class, \"column1\");\n        SimplePath\u003cString\u003e column2 = Expressions.simplePath(String.class, \"column2\");\n\n        // prepare with operator\n        SimplePath\u003cVoid\u003e withSubquery = Expressions.path(Void.class, \"CTE_SUBQUERY\");\n        SQLQuery withQuery = (SQLQuery) ormQueryFactory.buildQuery().with(\n                withSubquery,\n                column1,\n                column2\n        ).as(SQLExpressions\n                .select(testColumn11.as(\"column1\"), testColumn12.as(\"column2\"))\n                .from(unionTable1));\n\n        // first union subquery\n        SQLQuery\u003cTuple\u003e query1 = SQLExpressions\n                .select(column1, column2)\n                .from(withSubquery).where(column2.eq(\"data1\"));\n        // second union subquery\n        SQLQuery\u003cTuple\u003e query2 = SQLExpressions\n                .select(column1, column2)\n                .from(withSubquery).where(column2.eq(\"data2\"));\n\n        // create UnionBuilder\n         // if you want cache the result you can use selectCache() instead of select()\n        UnionBuilder unionBuilder = ormQueryFactory.select()\n                .unionAll(ormQueryFactory.buildQuery(), query1, query2);\n        // result order by\n        unionBuilder\n                .orderBy(\"column1\").desc().orderBy(\"column2\").asc();\n        // offset and limit (offset = 0, limit = 2 )\n        unionBuilder.limit(new Range(0, 2));\n        // group by result\n        unionBuilder.groupBy(\"column1\", \"column2\");\n\n        // build union query with \"with\" operator\n\n        SQLQuery unionSubQuery = unionBuilder.getUnionSubQuery();\n        ProjectableSQLQuery sqlQuery = withQuery.select(column1, column2)\n                .from(unionSubQuery.select(column1, column2));\n\n        // show final SQL\n        assertEquals(ormQueryFactory.select().rawSelect(sqlQuery).showSql(column1, column2),\n                \"with \\\"CTE_SUBQUERY\\\" (\\\"column1\\\", \\\"column2\\\") as (select \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_1\\\" as \\\"column1\\\", \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_2\\\" as \\\"column2\\\"\\n\" +\n                        \"from \\\"UNIONTABLE1\\\" \\\"UNIONTABLE1\\\")\\n\" +\n                        \"select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from (select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from ((select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from \\\"CTE_SUBQUERY\\\"\\n\" +\n                        \"where \\\"column2\\\" = 'data1')\\n\" +\n                        \"union all\\n\" +\n                        \"(select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from \\\"CTE_SUBQUERY\\\"\\n\" +\n                        \"where \\\"column2\\\" = 'data2')) as \\\"union\\\"\\n\" +\n                        \"group by \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"order by \\\"column1\\\" desc, \\\"column2\\\" asc\\n\" +\n                        \"limit 2\\n\" +\n                        \"offset 0)\");\n        // fetch data (if you want cache the result you can use selectCache() instead of select() )\n        List\u003cRawModel\u003e rawModels = ormQueryFactory.select().rawSelect(sqlQuery).findAll(column1, column2);\n        RawModel rawModel = rawModels.get(0);\n        String column1Value = rawModel.getColumnValue(column1);\n        String column2Value = rawModel.getColumnValue(column2);\n```\n#  count CTE operator (cacheable)\n\n```java\n        // create database schema\n        qDynamicTableFactory.buildTables(\"UnionTable1\")\n                .columns().addStringColumn(\"Id1\").size(255).useAsPrimaryKey().createColumn()\n                .addDateTimeColumn(\"modificationTime1\").notNull().createColumn()\n                .addStringColumn(\"TestColumn1_1\").size(255).createColumn()\n                .addStringColumn(\"TestColumn1_2\").size(255).createColumn()\n                .endColumns()\n                .primaryKey().addPrimaryKeyGenerator(PrimaryKeyGenerators.UUID.getPkGenerator()).endPrimaryKey()\n                .addVersionColumn(\"modificationTime1)\n                .endBuildTables()\n                .buildSchema();\n\n       // get unionTable1 Metadata\n        QDynamicTable unionTable1 = qDynamicTableFactory.getQDynamicTableByName(\"UnionTable1\");\n        // get column from unionTable1\n        StringPath testColumn11 = unionTable1.getStringColumnByName(\"TestColumn1_1\");\n        StringPath testColumn12 = unionTable1.getStringColumnByName(\"TestColumn1_2\");\n\n        SimplePath\u003cString\u003e column1 = Expressions.simplePath(String.class, \"column1\");\n        SimplePath\u003cString\u003e column2 = Expressions.simplePath(String.class, \"column2\");\n\n\n        SimplePath\u003cVoid\u003e withSubquery = Expressions.path(Void.class, \"CTE_SUBQUERY\");\n\n        SQLQuery withQuery = (SQLQuery) ormQueryFactory.buildQuery().with(\n                withSubquery,\n                column1,\n                column2\n        ).as(SQLExpressions\n                .select(testColumn11.as(\"column1\"), testColumn12.as(\"column2\"))\n                .from(unionTable1));\n\n        // first subquery\n        SQLQuery\u003cTuple\u003e query1 = SQLExpressions\n                .select(column1, column2)\n                .from(withSubquery).where(column2.eq(\"data1\"));\n        // second subquery\n        SQLQuery\u003cTuple\u003e query2 = SQLExpressions\n                .select(column1, column2)\n                .from(withSubquery).where(column2.eq(\"data2\"));\n\n        // create UnionBuilder\n        UnionBuilder unionBuilder = ormQueryFactory.select()\n                .unionAll(ormQueryFactory.buildQuery(), query1, query2);\n        // result order by\n        unionBuilder\n                .orderBy(\"column1\").desc().orderBy(\"column2\").asc();\n        // offset and limit (offset = 0, limit = 2 )\n        unionBuilder.limit(new Range(0, 4));\n        // group by result\n        unionBuilder.groupBy(\"column1\", \"column2\");\n\n        SQLQuery unionSubQuery = unionBuilder.getUnionSubQuery();\n        ProjectableSQLQuery sqlQuery = withQuery.select(column1, column2)\n                .from(unionSubQuery.select(column1, column2));\n\n        assertEquals(ormQueryFactory.select().rawSelect(sqlQuery).showSql(Wildcard.count),\n                \"with \\\"CTE_SUBQUERY\\\" (\\\"column1\\\", \\\"column2\\\") as (select \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_1\\\" as \\\"column1\\\", \\\"UNIONTABLE1\\\".\\\"TESTCOLUMN1_2\\\" as \\\"column2\\\"\\n\" +\n                        \"from \\\"UNIONTABLE1\\\" \\\"UNIONTABLE1\\\")\\n\" +\n                        \"select count(*)\\n\" +\n                        \"from (select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from ((select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from \\\"CTE_SUBQUERY\\\"\\n\" +\n                        \"where \\\"column2\\\" = 'data1')\\n\" +\n                        \"union all\\n\" +\n                        \"(select \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"from \\\"CTE_SUBQUERY\\\"\\n\" +\n                        \"where \\\"column2\\\" = 'data2')) as \\\"union\\\"\\n\" +\n                        \"group by \\\"column1\\\", \\\"column2\\\"\\n\" +\n                        \"order by \\\"column1\\\" desc, \\\"column2\\\" asc\\n\" +\n                        \"limit 4\\n\" +\n                        \"offset 0)\");\n\n        //fetch data and put result to the cache\n        RawModel rawModel = ormQueryFactory.selectCache().rawSelect(sqlQuery).findOne(Wildcard.count);\n        Long countValue = rawModel.getAliasValue(Wildcard.count);\n\n        //fetch data from the cache\n        RawModel rawModelFromCache = ormQueryFactory.selectCache().rawSelect(sqlQuery).findOne(Wildcard.count);\n        Long countValueCache = rawModelFromCache.getAliasValue(Wildcard.count);\n\n        // insert to unionTable1\n        insert1(\"newValue\", \"data1\"); // ormQueryFactory.insert(dynamicTableModel);\n        \n        // cache is automatically evicted then get a new value and result put to the cache\n        RawModel rawModelAndPutNewCache = ormQueryFactory.selectCache().rawSelect(sqlQuery).findOne(Wildcard.count);\n        Long newCountValue = rawModelAndPutNewCache.getAliasValue(Wildcard.count);\n\n        \n```\n#  Composite Primary key\n\n```java\n        // create Database schema\n        qDynamicTableFactory\n                .buildTables(\"testDynamicTableWithCompositeKey\")\n                .columns().addNumberColumn(\"id1\", Integer.class)\n                .useAsPrimaryKey().createColumn()\n                .addStringColumn(\"id2\").size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"testColumn\").size(255).createColumn()\n                .endColumns().endBuildTables().buildSchema();\n\n        // get dynamic table\n        QDynamicTable table = qDynamicTableFactory\n                .getQDynamicTableByName(\"testDynamicTableWithCompositeKey\");\n\n        // insert Data\n        DynamicTableModel dynamicTableModel = new DynamicTableModel(table);\n        dynamicTableModel.addColumnValue(\"Id1\", 1);\n        dynamicTableModel.addColumnValue(\"Id2\", \"2\");\n        dynamicTableModel.addColumnValue(\"testColumn\", \"test\");\n        ormQueryFactory.insert(dynamicTableModel);\n\n        List\u003cDynamicTableModel\u003e models = ormQueryFactory.selectCache().findAll(table);\n        assertNotNull(models);\n        assertEquals(models.size(), 1);\n        assertEquals(models.get(0).getValue(\"Id1\", Integer.class), Integer.valueOf(1));\n        assertEquals(models.get(0).getValue(\"Id2\", String.class), \"2\");\n        assertEquals(models.get(0).getValue(\"testColumn\", String.class), \"test\");\n```\n\n#  remove column from the Composite key\n\n```java\n        // create Database schema\n        qDynamicTableFactory\n                .buildTables(\"testDynamicTableWithCompositeKey\")\n                .columns().addNumberColumn(\"id1\", Integer.class)\n                .useAsPrimaryKey().createColumn()\n                .addStringColumn(\"id2\").size(255).useAsPrimaryKey().createColumn()\n                .addStringColumn(\"testColumn\").size(255).createColumn()\n                .endColumns().endBuildTables().buildSchema();\n\n        //  remove Id2 from primary key\n        qDynamicTableFactory\n                .buildTables(table.getTableName())\n                .primaryKey()\n                .removePrimaryKey(\"Id2\")\n                .endPrimaryKey()\n                .endBuildTables().buildSchema();\n        //  set column Id2 as nullable\n        qDynamicTableFactory\n                .buildTables(table.getTableName())\n                .columns().modifyColumn().nullable(\"Id2\").finish().endColumns()\n                .endBuildTables().buildSchema();\n\n        // insert Data without Id2\n        DynamicTableModel dynamicTableModel1 = new DynamicTableModel(table);\n        dynamicTableModel1.addColumnValue(\"Id1\", 1);\n        dynamicTableModel1.addColumnValue(\"testColumn\", \"test\");\n        ormQueryFactory.insert(dynamicTableModel1);\n```\n# If you find these useful, please [Donate](https://secure.wayforpay.com/button/b8de34ba8b4ab)!  \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvzakharchenko%2Fdynamic-orm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvzakharchenko%2Fdynamic-orm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvzakharchenko%2Fdynamic-orm/lists"}