├── .gitignore ├── LICENSE ├── README.md ├── docs ├── allclasses-frame.html ├── allclasses-noframe.html ├── cn │ └── devezhao │ │ └── persist4j │ │ ├── BaseTest.html │ │ ├── DataAccessException.html │ │ ├── Entity.html │ │ ├── Field.html │ │ ├── Filter.html │ │ ├── PersistException.html │ │ ├── PersistManager.html │ │ ├── PersistManagerFactory.html │ │ ├── Query.html │ │ ├── Record.html │ │ ├── RecordTest.html │ │ ├── dialect │ │ ├── Dialect.html │ │ ├── DialectException.html │ │ ├── Editor.html │ │ ├── FieldType.html │ │ ├── MySQL5Dialect.html │ │ ├── OracleDialect.html │ │ ├── Type.html │ │ ├── editor │ │ │ ├── AbstractFieldEditor.html │ │ │ ├── AnyReferenceEditor.html │ │ │ ├── BinaryEditor.html │ │ │ ├── BoolEditor.html │ │ │ ├── CharEditor.html │ │ │ ├── DateEditor.html │ │ │ ├── DecimalEditor.html │ │ │ ├── DoubleEditor.html │ │ │ ├── IntEditor.html │ │ │ ├── LongEditor.html │ │ │ ├── NTextEditor.html │ │ │ ├── PrimaryEditor.html │ │ │ ├── ReferenceEditor.html │ │ │ ├── ReferenceListEditor.html │ │ │ ├── SmallIntEditor.html │ │ │ ├── StringEditor.html │ │ │ ├── TextEditor.html │ │ │ ├── TimeEditor.html │ │ │ ├── TimestampEditor.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── function │ │ │ ├── GetDateFunction.html │ │ │ ├── SqlFunction.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── h2 │ │ │ ├── H2Dialect.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── engine │ │ ├── ID.html │ │ ├── IDGenerator.html │ │ ├── JdbcSupport.html │ │ ├── NullValue.html │ │ ├── PersistManagerFactoryImpl.html │ │ ├── PersistManagerImpl.html │ │ ├── PersistManagerTest.html │ │ ├── SqlExecutorContext.html │ │ ├── StandardRecord.html │ │ ├── StatementCallback.html │ │ ├── WeakIDGenerator.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── exception │ │ ├── JdbcException.html │ │ ├── SqlExceptionConverter.html │ │ ├── SqlWarningException.html │ │ ├── jdbc │ │ │ ├── ConstraintViolationException.html │ │ │ ├── GenericJdbcException.html │ │ │ ├── LockAcquisitionException.html │ │ │ ├── SqlSyntaxException.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── metadata │ │ ├── BaseMeta.html │ │ ├── BaseMetaObject.html │ │ ├── CascadeModel.html │ │ ├── MetadataException.html │ │ ├── MetadataFactory.html │ │ ├── MetadataTest.html │ │ ├── MissingMetaExcetion.html │ │ ├── impl │ │ │ ├── AnyEntity.html │ │ │ ├── ConfigurationMetadataFactory.html │ │ │ ├── EntityImpl.html │ │ │ ├── FieldImpl.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ ├── query │ │ ├── AjqlQuery.html │ │ ├── AjqlResultImpl.html │ │ ├── BaseQuery.html │ │ ├── IQuery.html │ │ ├── NativeQuery.html │ │ ├── NativeQueryImpl.html │ │ ├── QueryException.html │ │ ├── QueryTest.html │ │ ├── QueryedRecord.html │ │ ├── Result.html │ │ ├── SlowLogger.html │ │ ├── compiler │ │ │ ├── CompileException.html │ │ │ ├── Compiler.html │ │ │ ├── JoinField.html │ │ │ ├── JoinTree.JoinNode.html │ │ │ ├── JoinTree.html │ │ │ ├── NestedSelectContext.html │ │ │ ├── ParameterItem.html │ │ │ ├── QueryCompiler.html │ │ │ ├── QueryCompilerTest.html │ │ │ ├── SelectItem.html │ │ │ ├── SelectItemType.html │ │ │ ├── antlr │ │ │ │ ├── AjQLLexer.html │ │ │ │ ├── AjQLParser.html │ │ │ │ ├── AjQLParserTokenTypes.html │ │ │ │ ├── ParserException.html │ │ │ │ ├── ParserHelper.html │ │ │ │ ├── ThrowerAjQLParser.html │ │ │ │ ├── package-frame.html │ │ │ │ ├── package-summary.html │ │ │ │ └── package-tree.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ ├── record │ │ ├── FieldValueException.html │ │ ├── JsonRecordCreator.html │ │ ├── RecordCreator.html │ │ ├── RecordVisitor.html │ │ ├── XmlBean.html │ │ ├── XmlRecordCreator.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ └── util │ │ ├── CaseInsensitiveMap.html │ │ ├── CaseInsensitiveMapTest.html │ │ ├── SqlHelper.html │ │ ├── StringHelper.html │ │ ├── XmlHelper.DTDEntityResolver.html │ │ ├── XmlHelper.ErrorLogger.html │ │ ├── XmlHelper.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── support │ │ ├── QueryHelper.html │ │ ├── SchemaExport.html │ │ ├── SchemaExportTest.html │ │ ├── SecurityPreferencesConfigurer.html │ │ ├── Table.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-files │ ├── index-1.html │ ├── index-10.html │ ├── index-11.html │ ├── index-12.html │ ├── index-13.html │ ├── index-14.html │ ├── index-15.html │ ├── index-16.html │ ├── index-17.html │ ├── index-18.html │ ├── index-19.html │ ├── index-2.html │ ├── index-20.html │ ├── index-21.html │ ├── index-22.html │ ├── index-23.html │ ├── index-24.html │ ├── index-25.html │ ├── index-26.html │ ├── index-3.html │ ├── index-4.html │ ├── index-5.html │ ├── index-6.html │ ├── index-7.html │ ├── index-8.html │ └── index-9.html ├── index.html ├── overview-frame.html ├── overview-summary.html ├── overview-tree.html ├── package-list ├── script.js ├── serialized-form.html └── stylesheet.css ├── lib └── ojdbc8.jar ├── pom.xml └── src ├── main ├── java │ └── cn │ │ └── devezhao │ │ └── persist4j │ │ ├── DataAccessException.java │ │ ├── Entity.java │ │ ├── Field.java │ │ ├── Filter.java │ │ ├── PersistException.java │ │ ├── PersistManager.java │ │ ├── PersistManagerFactory.java │ │ ├── Query.java │ │ ├── Record.java │ │ ├── dialect │ │ ├── Dialect.java │ │ ├── DialectException.java │ │ ├── Editor.java │ │ ├── FieldType.java │ │ ├── MySQL5Dialect.java │ │ ├── OracleDialect.java │ │ ├── Type.java │ │ ├── editor │ │ │ ├── AbstractFieldEditor.java │ │ │ ├── AnyReferenceEditor.java │ │ │ ├── BinaryEditor.java │ │ │ ├── BoolEditor.java │ │ │ ├── CharEditor.java │ │ │ ├── DateEditor.java │ │ │ ├── DateTimeEditor.java │ │ │ ├── DecimalEditor.java │ │ │ ├── DoubleEditor.java │ │ │ ├── IntEditor.java │ │ │ ├── LongEditor.java │ │ │ ├── NTextEditor.java │ │ │ ├── PrimaryEditor.java │ │ │ ├── ReferenceEditor.java │ │ │ ├── ReferenceListEditor.java │ │ │ ├── SmallIntEditor.java │ │ │ ├── StringEditor.java │ │ │ ├── TextEditor.java │ │ │ ├── TimeEditor.java │ │ │ └── TimestampEditor.java │ │ ├── function │ │ │ ├── GetDateFunction.java │ │ │ └── SqlFunction.java │ │ └── h2 │ │ │ └── H2Dialect.java │ │ ├── engine │ │ ├── ID.java │ │ ├── IDGenerator.java │ │ ├── JdbcSupport.java │ │ ├── NullValue.java │ │ ├── PersistManagerFactoryImpl.java │ │ ├── PersistManagerImpl.java │ │ ├── SqlExecutorContext.java │ │ ├── StandardRecord.java │ │ ├── StatementCallback.java │ │ └── WeakIDGenerator.java │ │ ├── exception │ │ ├── JdbcException.java │ │ ├── SqlExceptionConverter.java │ │ ├── SqlWarningException.java │ │ └── jdbc │ │ │ ├── ConstraintViolationException.java │ │ │ ├── DataTruncationException.java │ │ │ ├── GenericJdbcException.java │ │ │ ├── LockAcquisitionException.java │ │ │ └── SqlSyntaxException.java │ │ ├── metadata │ │ ├── BaseMeta.java │ │ ├── BaseMetaObject.java │ │ ├── CascadeModel.java │ │ ├── MetadataException.java │ │ ├── MetadataFactory.java │ │ ├── MissingMetaExcetion.java │ │ └── impl │ │ │ ├── AnyEntity.java │ │ │ ├── ConfigurationMetadataFactory.java │ │ │ ├── EntityImpl.java │ │ │ └── FieldImpl.java │ │ ├── query │ │ ├── AjqlQuery.java │ │ ├── AjqlResultImpl.java │ │ ├── BaseQuery.java │ │ ├── IQuery.java │ │ ├── NativeQuery.java │ │ ├── NativeQueryImpl.java │ │ ├── QueryException.java │ │ ├── QueryedRecord.java │ │ ├── Result.java │ │ ├── SlowLogger.java │ │ └── compiler │ │ │ ├── CompileException.java │ │ │ ├── JoinField.java │ │ │ ├── JoinTree.java │ │ │ ├── NestedSelectContext.java │ │ │ ├── ParameterItem.java │ │ │ ├── QueryCompiler.java │ │ │ ├── SelectItem.java │ │ │ ├── SelectItemType.java │ │ │ ├── antlr │ │ │ ├── AjQLLexer.java │ │ │ ├── AjQLParser.java │ │ │ ├── AjQLParserTokenTypes.java │ │ │ ├── ParserException.java │ │ │ ├── ParserHelper.java │ │ │ ├── ThrowerAjQLParser.java │ │ │ └── ajql.g │ │ │ └── antlr4 │ │ │ └── ajql.g4 │ │ ├── record │ │ ├── FieldValueException.java │ │ ├── JsonRecordCreator.java │ │ ├── RecordCreator.java │ │ ├── RecordVisitor.java │ │ ├── XmlBean.java │ │ └── XmlRecordCreator.java │ │ └── util │ │ ├── CaseInsensitiveMap.java │ │ ├── SqlHelper.java │ │ ├── StringHelper.java │ │ ├── XmlHelper.java │ │ └── support │ │ ├── QueryHelper.java │ │ ├── SchemaExport.java │ │ ├── SecurityPreferencesConfigurer.java │ │ └── Table.java └── resources │ └── metadata.dtd └── test ├── java └── cn │ └── devezhao │ └── persist4j │ ├── BaseTest.java │ ├── RecordTest.java │ ├── engine │ └── PersistManagerTest.java │ ├── metadata │ └── MetadataTest.java │ ├── query │ ├── QueryTest.java │ └── compiler │ │ ├── Compiler.java │ │ └── QueryCompilerTest.java │ ├── record │ └── RecordVisitorTest.java │ └── util │ ├── CaseInsensitiveMapTest.java │ ├── StringHelperTest.java │ └── support │ └── SchemaExportTest.java └── resources └── metadata-test.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | # Windows image file caches 25 | Thumbs.db 26 | ehthumbs.db 27 | 28 | # Folder config file 29 | Desktop.ini 30 | 31 | # Recycle Bin used on file shares 32 | $RECYCLE.BIN/ 33 | 34 | # Eclipse 35 | /.settings 36 | /.classpath 37 | /.project 38 | 39 | # Windows Installer files 40 | *.cab 41 | *.msi 42 | *.msm 43 | *.msp 44 | 45 | # Windows shortcuts 46 | *.lnk 47 | 48 | # ========================= 49 | # Operating System Files 50 | # ========================= 51 | 52 | # OSX 53 | # ========================= 54 | 55 | .DS_Store 56 | .AppleDouble 57 | .LSOverride 58 | 59 | # Thumbnails 60 | ._* 61 | 62 | # Files that might appear in the root of a volume 63 | .DocumentRevisions-V100 64 | .fseventsd 65 | .Spotlight-V100 66 | .TemporaryItems 67 | .Trashes 68 | .VolumeIcon.icns 69 | 70 | # Directories potentially created on remote AFP share 71 | .AppleDB 72 | .AppleDesktop 73 | Network Trash Folder 74 | Temporary Items 75 | .apdisk 76 | /target/ 77 | /.settings/ 78 | /TESTDB/ 79 | derby.log 80 | 81 | #IDEA 82 | /.idea 83 | *.iml 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Use by Jitpack 2 | 3 | [![JitPack](https://jitpack.io/v/devezhao/persist4j.svg)](https://jitpack.io/#devezhao/persist4j) 4 | [![JavaDoc](https://img.shields.io/badge/java-doc-red.svg)](https://devezhao.github.io/persist4j/index.html) 5 | 6 | ## Maven 7 | 8 | ``` 9 | 10 | 11 | jitpack.io 12 | https://jitpack.io 13 | 14 | 15 | 16 | 17 | 18 | com.github.devezhao 19 | persist4j 20 | LAST_VERSION 21 | 22 | 23 | ``` 24 | 25 | ## 如何使用 26 | 27 | ### 基础操作对象 28 | 29 | 使用 [persist4j](https://github.com/devezhao/persist4j) 首先需要了解两个基础对象 `Record` 和 `Query`。`Record` 是一个 Map 实现,他承担了 DAO 职责,而 `Query` 是查询入口,是日常编码中使用最为频繁的类。 30 | 31 | #### Record 对象 32 | 33 | `Record` 包含了诸多 setter 和 getter 方法,在实现动态化 DAO 职责的同时,还具备对不同数据(字段)类型进行校验的能力。以下是一个基本的使用示例。 34 | 35 | ``` 36 | // 获取数据管理对象 37 | PersistManagerFactory PMF = ... 38 | PersistManager PM = PMF.createPersistManager(); 39 | 40 | Record record = new StandardRecord() 41 | record.setString("FieldName", "FieldValue"); 42 | 43 | PM.create(record); 44 | ``` 45 | 46 | > 通常你可以将上述代码封装为一个工具方法进行使用 47 | 48 | #### Query 对象 49 | 50 | `Query` 的使用主要是对 persist4j 独有的 AJQL (Auto Join Query Language)语句进行理解。AJQL 是 Like-SQL 语法,因此学习和理解起来并不困难。 51 | 52 | ``` 53 | // 获取数据管理对象 54 | PersistManagerFactory PMF = ... 55 | PersistManager PM = PMF.createPersistManager(); 56 | 57 | String ajql = "select Field1, ReferenceField1.Field2 from Table1 where Field2 = ?"; 58 | Record found = PM.createQuery(ajql).setParameter(1, "SomeValue").unique(); 59 | ``` 60 | 61 | > 通常你可以将上述代码封装为一个工具方法进行使用 62 | 63 | 请注意上例中 select 子句中的 `ReferenceField1.Field2` 字段,`ReferenceField1` 是一个引用型字段,因此可以使用 `.` 进行(自动)关联查询(其中 `Field2` 是关联表中的字段)。如果 `Field2` 也是一个引用字段,那么可以继续进行关联查询。 64 | 65 | 可以看出,通过 AJQL 可以大大简化我们日常查询 SQL 中的表关联操作,同时这也正是 AJQL 名称的由来。 66 | 67 | #### Query 自动装箱 68 | 69 | 经由 `Query` 查询出来的数据并不一定是数据库底层的数据类型,例如 `ID` 主键虽然使用 `varchar` 存储,但是查询后会自动转换为 `ID` 对象(其他字段同理)。这是因为我们会根据元数据的字段定义将其自动装箱,而无需你手动二次处理,同时也保证了数据的严谨性。 70 | 71 | ### 元数据 72 | 73 | 动态元数据是支撑 [persist4j](https://github.com/devezhao/persist4j) 的核心,使用 XML 配置,也可以将其存储在数据库中动态加载。无论何种方式没有本质区别,仅在与来源不同。 74 | 75 | ``` 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | ``` 86 | 87 | 以上示例片段来自 [rebuild](https://github.com/getrebuild/rebuild/) 项目,他定义了一个 `ProjectConfig` 实体及其所拥有的字段。关于各配置项的说明,请参考 [metadata.dtd](https://github.com/devezhao/persist4j/blob/master/src/main/resources/metadata.dtd) 。 88 | 89 | 元数据的配置最终会被映射为 `Entity` 和 `Field` 对象,可以对元数据进行操作。 90 | 91 | #### 主键 ID 92 | 93 | `ID` 对象即主键对象,其生成规则为 `([0-9]{3}-[0-9a-h]{16})`,其中前 3 位为实体码(不足 3 位前面补 0),其后为 `-` 分隔符,最后为 16 位随机 Hash 码(不区分大小写)。可以看出,通过 ID 我们可以识别其属于哪个实体。 94 | 95 | ### 最佳实践 96 | 97 | 我们建议你将 [persist4j](https://github.com/devezhao/persist4j) 与 Spring 配合使用,可以大大简化编码。当然,这不是必须的。通过参考 [rebuild](https://github.com/getrebuild/rebuild/) 项目你可以进行更多的了解。 98 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/dialect/editor/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.dialect.editor (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.dialect.editor

14 |
15 |

16 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/dialect/function/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.dialect.function (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.dialect.function

14 |
15 |

接口

16 | 19 |

20 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/dialect/h2/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.dialect.h2 (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.dialect.h2

14 |
15 |

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/dialect/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.dialect (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.dialect

14 |
15 |

接口

16 | 20 |

21 | 27 |

异常错误

28 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/engine/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.engine (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.engine

14 |
15 |

接口

16 | 19 |

20 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/exception/jdbc/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.exception.jdbc (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.exception.jdbc

14 |
15 |

异常错误

16 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/exception/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.exception (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.exception

14 |
15 |

16 | 19 |

异常错误

20 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/metadata/impl/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.metadata.impl (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.metadata.impl

14 |
15 |

16 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/metadata/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.metadata (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.metadata

14 |
15 |

接口

16 | 20 |

21 | 24 |

枚举

25 | 28 |

异常错误

29 | 33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j

14 |
15 |

接口

16 | 25 |

异常错误

26 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/query/compiler/antlr/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.query.compiler.antlr (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.query.compiler.antlr

14 |
15 |

接口

16 | 19 |

20 | 26 |

异常错误

27 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/query/compiler/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.query.compiler (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.query.compiler

14 |
15 |

接口

16 | 19 |

20 | 27 |

枚举

28 | 31 |

异常错误

32 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/query/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.query (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.query

14 |
15 |

接口

16 | 21 |

22 | 30 |

异常错误

31 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/record/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.record (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.record

14 |
15 |

接口

16 | 19 |

20 | 26 |

异常错误

27 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/util/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.util (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.util

14 |
15 |

16 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/cn/devezhao/persist4j/util/support/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | cn.devezhao.persist4j.util.support (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |

cn.devezhao.persist4j.util.support

14 |
15 |

16 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 已过时的列表 (persist4j) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
跳过导航链接
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

已过时的 API

74 |

目录

75 | 78 |
79 |
80 | 81 | 82 | 97 |
98 | 99 |
100 | 101 | 102 |
跳过导航链接
103 | 104 | 105 | 106 | 115 |
116 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | persist4j 8 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | <noscript> 69 | <div>您的浏览器已禁用 JavaScript。</div> 70 | </noscript> 71 | <h2>框架预警</h2> 72 | <p>请使用框架功能查看此文档。如果看到此消息, 则表明您使用的是不支持框架的 Web 客户机。链接到<a href="overview-summary.html">非框架版本</a>。</p> 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /docs/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 概览列表 (persist4j) 8 | 9 | 10 | 11 | 12 | 13 |
所有类
14 |
15 |

程序包

16 | 34 |
35 |

 

36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/package-list: -------------------------------------------------------------------------------- 1 | cn.devezhao.persist4j 2 | cn.devezhao.persist4j.dialect 3 | cn.devezhao.persist4j.dialect.editor 4 | cn.devezhao.persist4j.dialect.function 5 | cn.devezhao.persist4j.dialect.h2 6 | cn.devezhao.persist4j.engine 7 | cn.devezhao.persist4j.exception 8 | cn.devezhao.persist4j.exception.jdbc 9 | cn.devezhao.persist4j.metadata 10 | cn.devezhao.persist4j.metadata.impl 11 | cn.devezhao.persist4j.query 12 | cn.devezhao.persist4j.query.compiler 13 | cn.devezhao.persist4j.query.compiler.antlr 14 | cn.devezhao.persist4j.record 15 | cn.devezhao.persist4j.util 16 | cn.devezhao.persist4j.util.support 17 | -------------------------------------------------------------------------------- /docs/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/ojdbc8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devezhao/persist4j/0ab849caeafc10b45145f9e27f9a8b026ef116c0/lib/ojdbc8.jar -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | cn.devezhao 7 | persist4j 8 | 1.8.2 9 | jar 10 | 11 | persist4j 12 | https://github.com/devezhao/persist4j 13 | 14 | 15 | 16 | The Apache Software License, Version 2.0 17 | https://www.apache.org/licenses/LICENSE-2.0.txt 18 | repo 19 | 20 | 21 | 22 | 23 | UTF-8 24 | -Dfile.encoding=UTF-8 25 | true 26 | 4.3.30.RELEASE 27 | 28 | 29 | 30 | 31 | 32 | org.apache.maven.plugins 33 | maven-compiler-plugin 34 | 3.8.0 35 | 36 | 1.8 37 | 1.8 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | jitpack.io 47 | https://jitpack.io 48 | 49 | 50 | 51 | 52 | 53 | junit 54 | junit 55 | 4.13.2 56 | test 57 | 58 | 59 | com.h2database 60 | h2 61 | 2.1.214 62 | test 63 | 64 | 65 | com.github.devezhao 66 | commons 67 | 1.3.13 68 | 69 | 70 | antlr 71 | antlr 72 | 2.7.7 73 | 74 | 75 | jaxen 76 | jaxen 77 | 1.1.6 78 | 79 | 80 | org.springframework 81 | spring-core 82 | ${spring.version} 83 | 84 | 85 | org.springframework 86 | spring-beans 87 | ${spring.version} 88 | 89 | 90 | org.springframework 91 | spring-jdbc 92 | ${spring.version} 93 | 94 | 95 | com.alibaba 96 | druid 97 | 1.2.10 98 | 99 | 100 | mysql 101 | mysql-connector-java 102 | 5.1.49 103 | 104 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/DataAccessException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import org.apache.commons.lang.exception.NestableRuntimeException; 4 | 5 | /** 6 | * 数据访问错误 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 15, 2009 10 | * @version $Id: DataAccessException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public class DataAccessException extends NestableRuntimeException { 13 | private static final long serialVersionUID = -8609924407313152851L; 14 | 15 | public DataAccessException() { 16 | super(); 17 | } 18 | 19 | public DataAccessException(String msg) { 20 | super(msg); 21 | } 22 | 23 | public DataAccessException(String msg, Throwable cause) { 24 | super(msg, cause); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/Entity.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.metadata.BaseMeta; 4 | 5 | /** 6 | * 实体 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Jan 22, 2009 10 | * @version $Id: Entity.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public interface Entity extends BaseMeta { 13 | 14 | /** 15 | * 获取实体编号 16 | * 17 | * @return 18 | */ 19 | Integer getEntityCode(); 20 | 21 | /** 22 | * 获取主键字段 23 | * 24 | * @return 25 | */ 26 | Field getPrimaryField(); 27 | 28 | /** 29 | * 获取名称字段 30 | * 31 | * @return 32 | */ 33 | Field getNameField(); 34 | 35 | /** 36 | * 获取字段 37 | * 38 | * @param aName 39 | * @return 40 | */ 41 | Field getField(String aName); 42 | 43 | /** 44 | * 是否包含指定名称字段 45 | * 46 | * @param aName 47 | * @return 48 | */ 49 | boolean containsField(String aName); 50 | 51 | /** 52 | * 获取全部字段 53 | * 54 | * @return 55 | */ 56 | Field[] getFields(); 57 | 58 | /** 59 | * 获取引用到此实体的所有字段 60 | * 61 | * @return 62 | * @see #getReferenceToFields(boolean, boolean) 63 | */ 64 | Field[] getReferenceToFields(); 65 | 66 | /** 67 | * 获取引用到此实体的所有字段 68 | * 69 | * @param excludeNReference 是否排除多引用 70 | * @param excludeAnyReference 是否排除任意引用 71 | * @return 72 | */ 73 | Field[] getReferenceToFields(boolean excludeNReference, boolean excludeAnyReference); 74 | 75 | /** 76 | * 获取主实体(如有) 77 | * 78 | * @return 79 | */ 80 | Entity getMainEntity(); 81 | 82 | /** 83 | * 获取明细实体(如有) 84 | * 85 | * @return 86 | */ 87 | Entity getDetailEntity(); 88 | 89 | /** 90 | * v1.7 91 | * 92 | * @return 93 | */ 94 | Entity[] getDetialEntities(); 95 | 96 | /** 97 | * 获取字段名称 98 | * 99 | * @return 100 | * @see #getFields() 101 | */ 102 | String[] getFieldNames(); 103 | 104 | /** 105 | * 是否可删除 106 | * 107 | * @return 108 | */ 109 | boolean isDeletable(); 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/Field.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.dialect.Type; 4 | import cn.devezhao.persist4j.metadata.BaseMeta; 5 | import cn.devezhao.persist4j.metadata.CascadeModel; 6 | 7 | /** 8 | * 字段 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Jan 22, 2009 12 | * @version $Id: Field.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public interface Field extends BaseMeta { 15 | 16 | /** 17 | * 获取字段类型 18 | * 19 | * @return 20 | */ 21 | Type getType(); 22 | 23 | /** 24 | * 获取此字段的所属实体 25 | * 26 | * @return 27 | */ 28 | Entity getOwnEntity(); 29 | 30 | /** 31 | * 用于多引用字段。 32 | * 如果是引用型字段,获取到其引用的实体。如果 `ref-entity=*` 会返回所有实体 33 | * 34 | * @return 35 | */ 36 | Entity[] getReferenceEntities(); 37 | 38 | /** 39 | * 如果是引用型字段,获取到其引用的实体 40 | * 41 | * @return 42 | */ 43 | Entity getReferenceEntity(); 44 | 45 | /** 46 | * 如果是引用型字段,获取其级联方式 47 | * @return 48 | */ 49 | CascadeModel getCascadeModel(); 50 | 51 | /** 52 | * 获取此字段的最大允许长度 53 | * 54 | * @return 55 | */ 56 | int getMaxLength(); 57 | 58 | /** 59 | * 是否可以为空 60 | * 61 | * @return 62 | */ 63 | boolean isNullable(); 64 | 65 | /** 66 | * 是否可重复。注意:保留字段,系统不会针对此属性做处理 67 | * 68 | * @return 69 | */ 70 | boolean isRepeatable(); 71 | 72 | /** 73 | * 是否为数据库自动填充值 74 | * 75 | * @return 76 | */ 77 | boolean isAutoValue(); 78 | 79 | /** 80 | * 默认值。注意:默认值由数据库进行填充,框架不会做任何处理,只在在生成SCHEMA的时候会生成默认值 81 | * 82 | * @return 83 | */ 84 | Object getDefaultValue(); 85 | 86 | /** 87 | * 小数位精度 88 | * 89 | * @return 90 | * @see cn.devezhao.persist4j.dialect.editor.DoubleEditor 91 | * @see cn.devezhao.persist4j.dialect.editor.DecimalEditor 92 | */ 93 | int getDecimalScale(); 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/Filter.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 查询过滤器 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 2, 2009 10 | * @version $Id: Filter.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public interface Filter extends Serializable { 13 | 14 | String evaluate(Entity entity); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/PersistException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import org.apache.commons.lang.exception.NestableRuntimeException; 4 | 5 | /** 6 | * top-level exception 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 8, 2009 10 | * @version $Id: PersistException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public class PersistException extends NestableRuntimeException { 13 | private static final long serialVersionUID = 3294784663323509115L; 14 | 15 | public PersistException(String message) { 16 | super(message); 17 | } 18 | 19 | public PersistException(String message, Throwable ex) { 20 | super(message, ex); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/PersistManager.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.engine.ID; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 持久化管理器 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 10, 2009 12 | * @version $Id: PersistManager.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public interface PersistManager extends Serializable { 15 | 16 | /** 17 | * 获取持久化管理器工场 18 | * 19 | * @return 20 | */ 21 | PersistManagerFactory getPersistManagerFactory(); 22 | 23 | /** 24 | * 保存记录 25 | * 26 | * @param record 27 | * @return 28 | * @throws DataAccessException 29 | */ 30 | Record save(Record record) throws DataAccessException; 31 | 32 | /** 33 | * 更新记录 34 | * 35 | * @param record 36 | * @return 37 | * @throws DataAccessException 38 | */ 39 | Record update(Record record) throws DataAccessException; 40 | 41 | /** 42 | * 保存或更新记录(根据主键值) 43 | * 44 | * @param record 45 | * @return 46 | * @throws DataAccessException 47 | */ 48 | Record saveOrUpdate(Record record) throws DataAccessException; 49 | 50 | /** 51 | * 删除记录(包含级联删除) 52 | * 53 | * @param id 54 | * @return 55 | * @throws DataAccessException 56 | */ 57 | int delete(ID id) throws DataAccessException; 58 | 59 | /** 60 | * 删除多调记录(包含级联删除) 61 | * 62 | * @param ids 63 | * @return 64 | * @throws DataAccessException 65 | */ 66 | int[] delete(ID[] ids) throws DataAccessException; 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/PersistManagerFactory.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.dialect.Dialect; 4 | import cn.devezhao.persist4j.engine.SqlExecutorContext; 5 | import cn.devezhao.persist4j.metadata.MetadataFactory; 6 | import cn.devezhao.persist4j.query.NativeQuery; 7 | 8 | import javax.sql.DataSource; 9 | import java.io.Serializable; 10 | 11 | /** 12 | * 持久化管理器工厂 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 10, 2009 16 | * @version $Id: PersistManagerFactory.java 51 2009-05-06 07:45:48Z 17 | * zhaofang123@gmail.com $ 18 | */ 19 | public interface PersistManagerFactory extends Serializable { 20 | 21 | DataSource getDataSource(); 22 | 23 | Dialect getDialect(); 24 | 25 | MetadataFactory getMetadataFactory(); 26 | 27 | SqlExecutorContext getSQLExecutorContext(); 28 | 29 | PersistManager createPersistManager(); 30 | 31 | Query createQuery(String ajql); 32 | 33 | Query createQuery(String ajql, Filter filter); 34 | 35 | NativeQuery createNativeQuery(String sql); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/Query.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.query.IQuery; 4 | import cn.devezhao.persist4j.query.Result; 5 | import cn.devezhao.persist4j.query.compiler.SelectItem; 6 | 7 | /** 8 | * 查询 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 2, 2009 12 | * @version $Id: Query.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public interface Query extends IQuery, Result { 15 | 16 | // --------------------------------------------------- 17 | 18 | Query setParameter(String name, Object value); 19 | 20 | Query setFilter(Filter filter); 21 | 22 | Entity getRootEntity(); 23 | 24 | SelectItem[] getSelectItems(); 25 | 26 | Result result(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/DialectException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | 5 | /** 6 | * 方言异常 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 14, 2009 10 | * @version $Id: DialectException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public class DialectException extends PersistException { 13 | private static final long serialVersionUID = -5320452369990541421L; 14 | 15 | public DialectException() { 16 | this("Unknow dialect error."); 17 | } 18 | 19 | public DialectException(String message) { 20 | super(message); 21 | } 22 | 23 | public DialectException(String message, Throwable ex) { 24 | super(message, ex); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/Editor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | import java.io.Serializable; 4 | import java.sql.PreparedStatement; 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | 8 | /** 9 | * 字段编辑者 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, Feb 12, 2009 13 | * @version $Id: Editor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 14 | */ 15 | public interface Editor extends Serializable { 16 | 17 | int getType(); 18 | 19 | void set(PreparedStatement pstmt, int index, Object value) throws SQLException; 20 | 21 | Object get(ResultSet rs, int index) throws SQLException; 22 | 23 | String getLiteral(ResultSet rs, int index) throws SQLException; 24 | 25 | String toLiteral(Object value); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/FieldType.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | import cn.devezhao.persist4j.dialect.editor.AnyReferenceEditor; 4 | import cn.devezhao.persist4j.dialect.editor.BinaryEditor; 5 | import cn.devezhao.persist4j.dialect.editor.BoolEditor; 6 | import cn.devezhao.persist4j.dialect.editor.CharEditor; 7 | import cn.devezhao.persist4j.dialect.editor.DateEditor; 8 | import cn.devezhao.persist4j.dialect.editor.DateTimeEditor; 9 | import cn.devezhao.persist4j.dialect.editor.DecimalEditor; 10 | import cn.devezhao.persist4j.dialect.editor.DoubleEditor; 11 | import cn.devezhao.persist4j.dialect.editor.IntEditor; 12 | import cn.devezhao.persist4j.dialect.editor.LongEditor; 13 | import cn.devezhao.persist4j.dialect.editor.NTextEditor; 14 | import cn.devezhao.persist4j.dialect.editor.PrimaryEditor; 15 | import cn.devezhao.persist4j.dialect.editor.ReferenceEditor; 16 | import cn.devezhao.persist4j.dialect.editor.ReferenceListEditor; 17 | import cn.devezhao.persist4j.dialect.editor.SmallIntEditor; 18 | import cn.devezhao.persist4j.dialect.editor.StringEditor; 19 | import cn.devezhao.persist4j.dialect.editor.TextEditor; 20 | import cn.devezhao.persist4j.dialect.editor.TimeEditor; 21 | import cn.devezhao.persist4j.dialect.editor.TimestampEditor; 22 | 23 | import java.io.Serializable; 24 | 25 | /** 26 | * 字段类型定义 27 | * 28 | * @author FANGFANG ZHAO 29 | * @since 0.1, May 25, 2009 30 | * @version $Id: FieldType.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 31 | */ 32 | public class FieldType implements Type, Serializable { 33 | private static final long serialVersionUID = 1L; 34 | 35 | public static final int NO_NEED_LENGTH = -1; 36 | public static final int DEFAULT_TEXT_LENGTH = 65535; // TEXT类型默认长度 37 | public static final int DEFAULT_STRING_LENGTH = 255; // STRING类型默认长度 38 | public static final int DEFAULT_PRECISION = 19; // 数字精度(整数位+小数位=精度) 39 | public static final int DEFAULT_DECIMAL_SCALE = 4; // 默认小数精度 40 | 41 | public static final Type PRIMARY = new FieldType(10001, "primary", new PrimaryEditor()); 42 | public static final Type REFERENCE = new FieldType(10002, "reference", new ReferenceEditor()); 43 | public static final Type ANY_REFERENCE = new FieldType(10003, "any-reference", new AnyReferenceEditor()); 44 | public static final Type REFERENCE_LIST = new FieldType(10004, "reference-list", new ReferenceListEditor()); 45 | 46 | public static final Type INT = new FieldType(10011, "int", new IntEditor()); 47 | public static final Type SMALL_INT = new FieldType(10012, "small-int", new SmallIntEditor()); 48 | public static final Type DOUBLE = new FieldType(10014, "double", new DoubleEditor()); 49 | public static final Type DECIMAL = new FieldType(10015, "decimal", new DecimalEditor()); 50 | public static final Type LONG = new FieldType(10016, "long", new LongEditor()); 51 | 52 | public static final Type DATE = new FieldType(10021, "date", new DateEditor()); 53 | public static final Type DATETIME = new FieldType(10022, "datetime", new DateTimeEditor()); 54 | public static final Type TIMESTAMP = new FieldType(10023, "timestamp", new TimestampEditor()); 55 | public static final Type TIME = new FieldType(10024, "time", new TimeEditor()); 56 | 57 | public static final Type CHAR = new FieldType(10031, "char", new CharEditor()); 58 | public static final Type STRING = new FieldType(10032, "string", new StringEditor()); 59 | public static final Type TEXT = new FieldType(10033, "text", new TextEditor()); 60 | 61 | public static final Type BOOL = new FieldType(10091, "bool", new BoolEditor()); 62 | public static final Type NTEXT = new FieldType(10092, "ntext", new NTextEditor()); 63 | public static final Type BINARY = new FieldType(10093, "binary", new BinaryEditor()); 64 | 65 | // ---- 66 | 67 | final private Integer mask; 68 | final private String name; 69 | final private Editor editor; 70 | 71 | private FieldType(Integer mask, String name, Editor editor) { 72 | this.mask = mask; 73 | this.name = name; 74 | this.editor = editor; 75 | } 76 | 77 | @Override 78 | public Integer getMask() { 79 | return mask; 80 | } 81 | 82 | @Override 83 | public String getName() { 84 | return name; 85 | } 86 | 87 | @Override 88 | public Editor getFieldEditor() { 89 | return editor; 90 | } 91 | 92 | @Override 93 | public int hashCode() { 94 | return super.hashCode() >>> getMask(); 95 | } 96 | 97 | @Override 98 | public boolean equals(Object obj) { 99 | if (!(obj instanceof Type)) { 100 | return false; 101 | } 102 | Type t2 = (Type) obj; 103 | return t2.getMask().equals(this.getMask()); 104 | } 105 | 106 | @Override 107 | public String toString() { 108 | return "<" + mask + ':' + name + '>'; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/MySQL5Dialect.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | import cn.devezhao.persist4j.engine.ID; 4 | 5 | import java.sql.Types; 6 | 7 | /** 8 | * MySQL 方言 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 5, 2009 12 | * @version $Id: MySQL5Dialect.java 20 2009-02-10 03:35:10Z 13 | * zhaofang123@gmail.com $ 14 | */ 15 | public class MySQL5Dialect extends Dialect { 16 | private static final long serialVersionUID = 9022968517851901342L; 17 | 18 | public MySQL5Dialect() { 19 | super(); 20 | final String idt = String.format("char(%d)", ID.getIDGenerator().getLength()); 21 | registerColumnType(FieldType.PRIMARY.getMask(), idt, Types.CHAR); 22 | registerColumnType(FieldType.REFERENCE.getMask(), idt, Types.CHAR); 23 | registerColumnType(FieldType.ANY_REFERENCE.getMask(), idt, Types.VARCHAR); 24 | registerColumnType(FieldType.REFERENCE_LIST.getMask(), "varchar(420)", Types.VARCHAR); // 最多支持20个ID(20位) 25 | registerColumnType(FieldType.INT.getMask(), "int(11)", Types.INTEGER); 26 | registerColumnType(FieldType.SMALL_INT.getMask(), "smallint(6)", Types.SMALLINT); 27 | registerColumnType(FieldType.DOUBLE.getMask(), "double(19, %d)", Types.DOUBLE); 28 | registerColumnType(FieldType.DECIMAL.getMask(), "decimal(29, %d)", Types.DECIMAL); 29 | registerColumnType(FieldType.LONG.getMask(), "bigint(20)", Types.BIGINT); 30 | registerColumnType(FieldType.CHAR.getMask(), "char(1)", Types.CHAR); 31 | registerColumnType(FieldType.STRING.getMask(), "varchar(%d)", Types.VARCHAR); 32 | registerColumnType(FieldType.TEXT.getMask(), "text(%d)", Types.VARCHAR); 33 | registerColumnType(FieldType.DATE.getMask(), "date", Types.DATE); 34 | registerColumnType(FieldType.TIMESTAMP.getMask(), "timestamp", Types.TIMESTAMP); 35 | registerColumnType(FieldType.DATETIME.getMask(), "datetime", Types.TIMESTAMP); 36 | registerColumnType(FieldType.TIME.getMask(), "time", Types.TIME); 37 | registerColumnType(FieldType.BOOL.getMask(), "char(1)", Types.CHAR); 38 | registerColumnType(FieldType.NTEXT.getMask(), "longtext", Types.LONGVARCHAR); 39 | registerColumnType(FieldType.BINARY.getMask(), "longblob", Types.BLOB); 40 | } 41 | 42 | @Override 43 | public String getDialectName() { 44 | return "mysql5"; 45 | } 46 | 47 | @Override 48 | public char getClosedQuote() { 49 | return QUOTED[0]; 50 | } 51 | 52 | @Override 53 | public char getStartQuote() { 54 | return QUOTED[1]; 55 | } 56 | 57 | @Override 58 | public String insertLimit(String query, int limit, int offset) { 59 | return query + 60 | " limit " + limit + 61 | (offset > 0 ? (" offset " + offset) : ""); 62 | } 63 | 64 | @Override 65 | public boolean supportsLimitOffset() { 66 | return Boolean.TRUE; 67 | } 68 | 69 | @Override 70 | public boolean supportsFullText() { 71 | return Boolean.TRUE; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/OracleDialect.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | import cn.devezhao.persist4j.engine.ID; 4 | 5 | import java.sql.Types; 6 | import java.util.Locale; 7 | 8 | /** 9 | * 10 | * @author zhaofang123@gmail.com 11 | * @since 12/10/2018 12 | */ 13 | public class OracleDialect extends Dialect { 14 | private static final long serialVersionUID = 5056057920212451174L; 15 | 16 | public OracleDialect() { 17 | super(); 18 | final String idt = String.format("CHAR(%d)", ID.getIDGenerator().getLength()); 19 | registerColumnType(FieldType.PRIMARY.getMask(), idt, Types.CHAR); 20 | registerColumnType(FieldType.REFERENCE.getMask(), idt, Types.CHAR); 21 | registerColumnType(FieldType.ANY_REFERENCE.getMask(), idt, Types.CHAR); 22 | registerColumnType(FieldType.REFERENCE_LIST.getMask(), "VARCHAR2(420)", Types.CHAR); 23 | registerColumnType(FieldType.INT.getMask(), "INT", Types.INTEGER); 24 | registerColumnType(FieldType.SMALL_INT.getMask(), "SMALLINT", Types.SMALLINT); 25 | registerColumnType(FieldType.DOUBLE.getMask(), "NUMBER(19, 8)", Types.NUMERIC); 26 | registerColumnType(FieldType.DECIMAL.getMask(), "NUMBER(19, 8)", Types.NUMERIC); 27 | registerColumnType(FieldType.LONG.getMask(), "LONG", Types.BIGINT); 28 | registerColumnType(FieldType.CHAR.getMask(), "CHAR(1)", Types.CHAR); 29 | registerColumnType(FieldType.STRING.getMask(), "VARCHAR2(%d)", Types.VARCHAR); 30 | registerColumnType(FieldType.TEXT.getMask(), "LONG VARCHAR", Types.LONGVARCHAR); 31 | registerColumnType(FieldType.DATE.getMask(), "DATE", Types.DATE); 32 | registerColumnType(FieldType.TIMESTAMP.getMask(), "TIMESTAMP", Types.TIMESTAMP); 33 | registerColumnType(FieldType.TIME.getMask(), "TIME", Types.TIME); 34 | registerColumnType(FieldType.BOOL.getMask(), "CHAR(1)", Types.CHAR); 35 | registerColumnType(FieldType.NTEXT.getMask(), "CLOB", Types.CLOB); 36 | registerColumnType(FieldType.BINARY.getMask(), "BLOB", Types.BLOB); 37 | } 38 | 39 | @Override 40 | public String getDialectName() { 41 | return "oracle"; 42 | } 43 | 44 | @Override 45 | public char getStartQuote() { 46 | return QUOTED[4]; 47 | } 48 | 49 | @Override 50 | public char getClosedQuote() { 51 | return QUOTED[4]; 52 | } 53 | 54 | @Override 55 | public String insertLimit(String query, int limit, int offset) { 56 | query = query.trim(); 57 | boolean isForUpdate = false; 58 | if (query.toLowerCase(Locale.ROOT).endsWith(" for update")) { 59 | query = query.substring(0, query.length() - 11); 60 | isForUpdate = true; 61 | } 62 | 63 | String pagingSelect; 64 | if (offset > 0) { 65 | pagingSelect = "select * from ( select row_.*, ROWNUM rownum_ from ( %s ) where rownum_ <= ? and rownum_ > ?"; 66 | pagingSelect = String.format(pagingSelect, query, limit + offset, offset); 67 | } else { 68 | pagingSelect = "select * from ( %s ) where ROWNUM <= %d"; 69 | pagingSelect = String.format(pagingSelect, query, limit); 70 | } 71 | 72 | if (isForUpdate) { 73 | pagingSelect += " for update"; 74 | } 75 | 76 | return pagingSelect; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/Type.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect; 2 | 3 | /** 4 | * 字段类型 5 | * 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, Jan 22, 2009 8 | * @version $Id: Type.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public interface Type { 11 | 12 | Integer getMask(); 13 | 14 | String getName(); 15 | 16 | Editor getFieldEditor(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/AbstractFieldEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.Editor; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | 11 | /** 12 | * 字段编辑者公用实现 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 12, 2009 16 | * @version $Id: AbstractFieldEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 17 | */ 18 | public abstract class AbstractFieldEditor implements Editor { 19 | private static final long serialVersionUID = 4896806840146314960L; 20 | 21 | protected static final Log LOG = LogFactory.getLog(AbstractFieldEditor.class); 22 | 23 | protected AbstractFieldEditor() { 24 | } 25 | 26 | @Override 27 | public Object get(ResultSet rs, int index) throws SQLException { 28 | return rs.getObject(index); 29 | } 30 | 31 | @Override 32 | public String getLiteral(ResultSet rs, int index) throws SQLException { 33 | return toLiteral( get(rs, index) ); 34 | } 35 | 36 | @Override 37 | public void set(PreparedStatement pstmt, int index, Object value) 38 | throws SQLException { 39 | pstmt.setObject(index, value); 40 | } 41 | 42 | @Override 43 | public String toLiteral(Object value) { 44 | return (value == null) ? null : value.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/AnyReferenceEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | /** 6 | * 单一引用(任意实体) 7 | * 8 | * @author zhaofang123@gmail.com 9 | * @since 12/28/2018 10 | */ 11 | public class AnyReferenceEditor extends ReferenceEditor { 12 | 13 | private static final long serialVersionUID = -7654860974427302836L; 14 | 15 | @Override 16 | public int getType() { 17 | return FieldType.ANY_REFERENCE.getMask(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/BinaryEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | import cn.devezhao.persist4j.dialect.FieldType; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | 12 | /** 13 | * 二进制 14 | * 15 | * @author FANGFANG ZHAO 16 | * @since 0.1, Feb 14, 2009 17 | * @version $Id: BinaryEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 18 | */ 19 | public class BinaryEditor extends AbstractFieldEditor { 20 | 21 | private static final long serialVersionUID = 3962501236650435747L; 22 | 23 | @Override 24 | public int getType() { 25 | return FieldType.BINARY.getMask(); 26 | } 27 | 28 | @Override 29 | public void set(PreparedStatement pstmt, int index, Object value) 30 | throws SQLException { 31 | InputStream stream = (InputStream) value; 32 | long size; 33 | try { 34 | // size = ByteUtils.size(stream); // NOTE does not read 35 | size = stream.available(); 36 | } catch (IOException e) { 37 | throw new PersistException("Cannot read size of stream", e); 38 | } 39 | if (size == 0) { 40 | System.out.println("## STREAM IS EMPTY"); 41 | } 42 | pstmt.setBinaryStream(index, stream, (int) size); 43 | } 44 | 45 | @Override 46 | public Object get(ResultSet rs, int index) throws SQLException { 47 | return rs.getBinaryStream(index); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/BoolEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 布尔 11 | * 12 | * @author FANGFANG ZHAO 13 | * @version $Id: BoolEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 14 | * @since 0.1, Feb 14, 2009 15 | */ 16 | public class BoolEditor extends CharEditor { 17 | private static final long serialVersionUID = -2740602793905099065L; 18 | 19 | public static final char TRUE = 'T'; 20 | public static final char FALSE = 'F'; 21 | 22 | @Override 23 | public int getType() { 24 | return FieldType.BOOL.getMask(); 25 | } 26 | 27 | @Override 28 | public void set(PreparedStatement pstmt, int index, Object value) 29 | throws SQLException { 30 | char ch = ((Boolean) value) ? TRUE : FALSE; 31 | super.set(pstmt, index, ch); 32 | } 33 | 34 | @Override 35 | public Object get(ResultSet rs, int index) throws SQLException { 36 | Object v = super.get(rs, index); 37 | if (v == null) { 38 | return null; 39 | } 40 | 41 | char ch = v.toString().toUpperCase().charAt(0); 42 | switch (ch) { 43 | case TRUE: 44 | return true; 45 | case FALSE: 46 | return false; 47 | default: 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/CharEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.sql.ResultSet; 6 | import java.sql.SQLException; 7 | 8 | /** 9 | * 单字符 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, Feb 14, 2009 13 | * @version $Id: CharEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 14 | */ 15 | public class CharEditor extends StringEditor { 16 | 17 | private static final long serialVersionUID = 8651192300226873094L; 18 | 19 | @Override 20 | public int getType() { 21 | return FieldType.CHAR.getMask(); 22 | } 23 | 24 | @Override 25 | public Object get(ResultSet rs, int index) throws SQLException { 26 | String v = rs.getString(index); 27 | return (v == null) ? null : v.charAt(0); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/DateEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 日期 11 | * 12 | * @author FANGFANG ZHAO 13 | * @since 0.1, Feb 14, 2009 14 | * @version $Id: DateEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 15 | */ 16 | public class DateEditor extends AbstractFieldEditor { 17 | 18 | private static final long serialVersionUID = -2499354201101231156L; 19 | 20 | @Override 21 | public int getType() { 22 | return FieldType.DATE.getMask(); 23 | } 24 | 25 | @Override 26 | public void set(PreparedStatement pstmt, int index, Object value) 27 | throws SQLException { 28 | java.sql.Date v; 29 | if (value.getClass() == java.util.Date.class) { 30 | v = new java.sql.Date( ((java.util.Date) value).getTime() ); 31 | } else { 32 | v = (java.sql.Date) value; 33 | } 34 | pstmt.setDate(index, v); 35 | } 36 | 37 | @Override 38 | public Object get(ResultSet rs, int index) throws SQLException { 39 | java.sql.Date v = rs.getDate(index); 40 | return (v == null) ? null : new java.util.Date(v.getTime()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/DateTimeEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | /** 6 | * 日期时间。兼容: Date, Long 7 | * 8 | * @author FF 9 | * @since 12/28/2024 10 | * @see TimestampEditor 11 | */ 12 | public class DateTimeEditor extends TimestampEditor { 13 | private static final long serialVersionUID = -8487826805942935988L; 14 | 15 | @Override 16 | public int getType() { 17 | return FieldType.DATETIME.getMask(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/DecimalEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.RoundingMode; 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | 11 | /** 12 | * 数字 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 14, 2009 16 | * @version $Id: DecimalEditor.java 52 2009-05-25 09:54:02Z 17 | * zhaofang123@gmail.com $ 18 | */ 19 | public class DecimalEditor extends AbstractFieldEditor { 20 | 21 | private static final long serialVersionUID = 3815050607620002543L; 22 | 23 | @Override 24 | public int getType() { 25 | return FieldType.DECIMAL.getMask(); 26 | } 27 | 28 | @Override 29 | public void set(PreparedStatement pstmt, int index, Object value) 30 | throws SQLException { 31 | set(pstmt, index, value, FieldType.DEFAULT_DECIMAL_SCALE); 32 | } 33 | 34 | public void set(PreparedStatement pstmt, int index, Object value, int scale) 35 | throws SQLException { 36 | if (value instanceof Double) { 37 | value = BigDecimal.valueOf((Double) value); 38 | } 39 | 40 | BigDecimal decimalValue = (BigDecimal) value; 41 | decimalValue = decimalValue 42 | .setScale(scale < 0 ? FieldType.DEFAULT_DECIMAL_SCALE : scale, RoundingMode.HALF_UP); 43 | pstmt.setBigDecimal(index, decimalValue); 44 | } 45 | 46 | @Override 47 | public Object get(ResultSet rs, int index) throws SQLException { 48 | return rs.getBigDecimal(index); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/DoubleEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.commons.ObjectUtils; 4 | import cn.devezhao.persist4j.dialect.FieldType; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.RoundingMode; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | 12 | /** 13 | * 双精度数字 14 | * 15 | * @author FANGFANG ZHAO 16 | * @since 0.1, Feb 14, 2009 17 | * @version $Id: DoubleEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 18 | */ 19 | public class DoubleEditor extends AbstractFieldEditor { 20 | 21 | private static final long serialVersionUID = 3370417172932258927L; 22 | 23 | @Override 24 | public int getType() { 25 | return FieldType.DOUBLE.getMask(); 26 | } 27 | 28 | @Override 29 | public void set(PreparedStatement pstmt, int index, Object value) 30 | throws SQLException { 31 | set(pstmt, index, value, FieldType.DEFAULT_DECIMAL_SCALE); 32 | } 33 | 34 | public void set(PreparedStatement pstmt, int index, Object value, int scale) 35 | throws SQLException { 36 | BigDecimal decimalValue; 37 | if (value instanceof BigDecimal) { 38 | decimalValue = (BigDecimal) value; 39 | } else { 40 | decimalValue = BigDecimal.valueOf((Double) value); 41 | } 42 | 43 | double doubleValue = decimalValue 44 | .setScale(scale < 0 ? FieldType.DEFAULT_DECIMAL_SCALE : scale, RoundingMode.HALF_UP) 45 | .doubleValue(); 46 | pstmt.setDouble(index, doubleValue); 47 | } 48 | 49 | @Override 50 | public Object get(ResultSet rs, int index) throws SQLException { 51 | Object hasVal = rs.getObject(index); 52 | return hasVal == null ? null : ObjectUtils.toDouble(hasVal); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/IntEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.commons.ObjectUtils; 4 | import cn.devezhao.persist4j.dialect.FieldType; 5 | 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | 10 | /** 11 | * 整数 12 | * 13 | * @author FANGFANG ZHAO 14 | * @since 0.1, Feb 12, 2009 15 | * @version $Id: IntEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 16 | */ 17 | public class IntEditor extends AbstractFieldEditor { 18 | 19 | private static final long serialVersionUID = 2845210116784771583L; 20 | 21 | @Override 22 | public int getType() { 23 | return FieldType.INT.getMask(); 24 | } 25 | 26 | @Override 27 | public void set(PreparedStatement pstmt, int index, Object value) 28 | throws SQLException { 29 | Integer intValue; 30 | if (value instanceof Long) { 31 | intValue = ((Long) value).intValue(); 32 | } else { 33 | intValue = (Integer) value; 34 | } 35 | pstmt.setInt(index, intValue); 36 | } 37 | 38 | @Override 39 | public Object get(ResultSet rs, int index) throws SQLException { 40 | Object hasVal = rs.getObject(index); 41 | return hasVal == null ? null : ObjectUtils.toInt(hasVal); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/LongEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.commons.ObjectUtils; 4 | import cn.devezhao.persist4j.dialect.FieldType; 5 | 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | 10 | /** 11 | * 长整数 12 | * 13 | * @author Zhao Fangfang 14 | * @since 0.2, 2010-12-4 15 | * @version $Id: LongEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 16 | */ 17 | public class LongEditor extends AbstractFieldEditor { 18 | 19 | private static final long serialVersionUID = 9216600570875846158L; 20 | 21 | @Override 22 | public int getType() { 23 | return FieldType.LONG.getMask(); 24 | } 25 | 26 | @Override 27 | public void set(PreparedStatement pstmt, int index, Object value) 28 | throws SQLException { 29 | Long longValue; 30 | if (value instanceof Integer) { 31 | longValue = ((Integer) value).longValue(); 32 | } else { 33 | longValue = (Long) value; 34 | } 35 | pstmt.setLong(index, longValue); 36 | } 37 | 38 | @Override 39 | public Object get(ResultSet rs, int index) throws SQLException { 40 | Object hasVal = rs.getObject(index); 41 | return hasVal == null ? null : ObjectUtils.toLong(hasVal); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/NTextEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.IOException; 7 | import java.io.Reader; 8 | import java.sql.Clob; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | 13 | /** 14 | * 大文本 15 | * 16 | * @author FANGFANG ZHAO 17 | * @since 0.1, Feb 14, 2009 18 | * @version $Id: NTextEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 19 | */ 20 | public class NTextEditor extends AbstractFieldEditor { 21 | 22 | private static final long serialVersionUID = -6531990086997201844L; 23 | 24 | @Override 25 | public int getType() { 26 | return FieldType.NTEXT.getMask(); 27 | } 28 | 29 | @Override 30 | public Object get(ResultSet rs, int index) throws SQLException { 31 | Object val = super.get(rs, index); 32 | return read2String(val); 33 | } 34 | 35 | /** 36 | * @param ntext 37 | * @return 38 | */ 39 | public Object read2String(Object ntext) { 40 | if (ntext == null) { 41 | return null; 42 | } 43 | else if (ntext instanceof Clob) { 44 | try (Reader reader = ((Clob) ntext).getCharacterStream()) { 45 | try (BufferedReader br = new BufferedReader(reader)) { 46 | StringBuilder sb = new StringBuilder(); 47 | String line = br.readLine(); 48 | while (line != null) { 49 | sb.append(line); 50 | line = br.readLine(); 51 | } 52 | ntext = sb.toString(); 53 | } 54 | 55 | } catch (Exception ex) { 56 | LOG.error("Reading Clob failed", ex); 57 | } 58 | } 59 | else if (ntext instanceof Reader) { 60 | try (BufferedReader br = ntext instanceof BufferedReader 61 | ? ((BufferedReader) ntext) : new BufferedReader((Reader) ntext)) { 62 | StringBuilder sb = new StringBuilder(); 63 | String line; 64 | try { 65 | while ((line = br.readLine()) != null) { 66 | sb.append(line); 67 | } 68 | ntext = sb.toString(); 69 | 70 | } catch (IOException ex) { 71 | LOG.error("Reading Reader failed", ex); 72 | } 73 | 74 | } catch (IOException ex) { 75 | LOG.error("Reading Reader failed", ex); 76 | } 77 | } 78 | 79 | return ntext; 80 | } 81 | 82 | @Override 83 | public void set(PreparedStatement pstmt, int index, Object value) 84 | throws SQLException { 85 | // Reader reader = null; 86 | // long size = 0; 87 | // if (Reader.class.isAssignableFrom(value.getClass())) { 88 | // reader = (Reader) value; 89 | // try { 90 | // size = ByteUtils.size(reader); 91 | // } catch (IOException e) { 92 | // throw new PersistException("can't read size of stream", e); 93 | // } 94 | // } else { 95 | // String v = value.toString(); 96 | // reader = new StringReader(v); 97 | // size = v.length(); 98 | // } 99 | // TASK can't put reader to column 100 | // pstmt.setCharacterStream(index, reader, (int) size); 101 | pstmt.setString(index, value.toString()); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/PrimaryEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | import cn.devezhao.persist4j.engine.ID; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | 11 | /** 12 | * 主键 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 12, 2009 16 | * @version $Id: PrimaryEditor.java 21 2009-02-12 15:44:18Z 17 | * zhaofang123@gmail.com $ 18 | */ 19 | public class PrimaryEditor extends StringEditor { 20 | 21 | private static final long serialVersionUID = -1490384633712480716L; 22 | 23 | @Override 24 | public int getType() { 25 | return FieldType.PRIMARY.getMask(); 26 | } 27 | 28 | @Override 29 | public void set(PreparedStatement pstmt, int index, Object value) 30 | throws SQLException { 31 | super.set(pstmt, index, ((ID) value).toLiteral()); 32 | } 33 | 34 | @Override 35 | public Object get(ResultSet rs, int index) throws SQLException { 36 | String v = rs.getString(index); 37 | return (StringUtils.isEmpty(v)) ? null : ID.valueOf(v); 38 | } 39 | 40 | @Override 41 | public String toLiteral(Object value) { 42 | return (value == null) ? null : ((ID) value).toLiteral(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/ReferenceEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | /** 6 | * 单一引用 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 12, 2009 10 | * @version $Id: ReferenceEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 11 | * @see AnyReferenceEditor 12 | */ 13 | public class ReferenceEditor extends PrimaryEditor { 14 | 15 | private static final long serialVersionUID = 6498270129310553155L; 16 | 17 | @Override 18 | public int getType() { 19 | return FieldType.REFERENCE.getMask(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/ReferenceListEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | import cn.devezhao.persist4j.engine.ID; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * 多引用(任意实体) 15 | * NOTE 存储为 ID 列表,更好的方式应为三方表 16 | * 17 | * @author zhaofang123@gmail.com 18 | * @since 12/28/2018 19 | */ 20 | public class ReferenceListEditor extends StringEditor { 21 | 22 | private static final long serialVersionUID = -7654860974427302836L; 23 | 24 | /** 25 | * ID 分隔符 26 | */ 27 | public static final String VALUE_SEP = ","; 28 | 29 | @Override 30 | public int getType() { 31 | return FieldType.REFERENCE_LIST.getMask(); 32 | } 33 | 34 | @Override 35 | public void set(PreparedStatement pstmt, int index, Object value) throws SQLException { 36 | String text = toLiteral(value); 37 | super.set(pstmt, index, text); 38 | } 39 | 40 | @Override 41 | public Object get(ResultSet rs, int index) throws SQLException { 42 | String v = rs.getString(index); 43 | if (StringUtils.isBlank(v)) { 44 | return null; 45 | } 46 | 47 | List ids = new ArrayList<>(); 48 | for (String id : v.split(",")) { 49 | ids.add(ID.valueOf(id)); 50 | } 51 | return ids.isEmpty() ? null : ids.toArray(new ID[0]); 52 | } 53 | 54 | @Override 55 | public String toLiteral(Object value) { 56 | if (value == null) { 57 | return null; 58 | } 59 | ID[] ids = (ID[]) value; 60 | return ids.length == 0 ? null : StringUtils.join(ids, VALUE_SEP); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/SmallIntEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | /** 6 | * 小整数 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 14, 2009 10 | * @version $Id: SmallIntEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 11 | */ 12 | public class SmallIntEditor extends IntEditor { 13 | 14 | private static final long serialVersionUID = 942326510267027292L; 15 | 16 | @Override 17 | public int getType() { 18 | return FieldType.SMALL_INT.getMask(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/StringEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | import cn.devezhao.persist4j.engine.NullValue; 5 | 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.sql.Types; 10 | 11 | /** 12 | * 字符串 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 12, 2009 16 | * @version $Id: StringEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 17 | */ 18 | public class StringEditor extends AbstractFieldEditor { 19 | 20 | private static final long serialVersionUID = 1570486266187499134L; 21 | 22 | @Override 23 | public int getType() { 24 | return FieldType.STRING.getMask(); 25 | } 26 | 27 | @Override 28 | public void set(PreparedStatement pstmt, int index, Object value) 29 | throws SQLException { 30 | if (value == null || NullValue.is(value)) { 31 | pstmt.setNull(index, Types.VARCHAR); 32 | } else { 33 | pstmt.setString(index, value.toString()); 34 | } 35 | } 36 | 37 | @Override 38 | public Object get(ResultSet rs, int index) throws SQLException { 39 | return rs.getString(index); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/TextEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | /** 6 | * 文本 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 14, 2009 10 | * @version $Id: TextEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 11 | */ 12 | public class TextEditor extends StringEditor { 13 | 14 | private static final long serialVersionUID = 7190173130419637496L; 15 | 16 | @Override 17 | public int getType() { 18 | return FieldType.TEXT.getMask(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/TimeEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.sql.Time; 9 | import java.time.LocalTime; 10 | import java.util.Date; 11 | 12 | /** 13 | * 时间。兼容: Date, LocalTime, Long 14 | * 15 | * @author devezhao 16 | * @since 2022/3/9 17 | */ 18 | public class TimeEditor extends AbstractFieldEditor { 19 | private static final long serialVersionUID = -2499354201101781156L; 20 | 21 | @Override 22 | public int getType() { 23 | return FieldType.TIME.getMask(); 24 | } 25 | 26 | @Override 27 | public void set(PreparedStatement pstmt, int index, Object value) 28 | throws SQLException { 29 | Time v; 30 | if (value.getClass() == Date.class) { 31 | v = new Time(((Date) value).getTime()); 32 | } else if (value.getClass() == LocalTime.class) { 33 | v = Time.valueOf((LocalTime) value); 34 | } else if (value instanceof Number) { 35 | v = new Time(((Number) value).longValue()); 36 | } else { 37 | v = (Time) value; 38 | } 39 | 40 | pstmt.setTime(index, v); 41 | } 42 | 43 | @Override 44 | public Object get(ResultSet rs, int index) throws SQLException { 45 | Time v = rs.getTime(index); 46 | return (v == null) ? null : v.toLocalTime(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/editor/TimestampEditor.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.editor; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.sql.Timestamp; 9 | import java.util.Date; 10 | 11 | /** 12 | * 日期时间。兼容: Date, Long 13 | * 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 14, 2009 16 | * @version $Id: TimestampEditor.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 17 | */ 18 | public class TimestampEditor extends DateEditor { 19 | 20 | private static final long serialVersionUID = -8487826805942935976L; 21 | 22 | @Override 23 | public int getType() { 24 | return FieldType.TIMESTAMP.getMask(); 25 | } 26 | 27 | @Override 28 | public void set(PreparedStatement pstmt, int index, Object value) 29 | throws SQLException { 30 | Timestamp v; 31 | Class vClazz = value.getClass(); 32 | if (vClazz == java.util.Date.class || vClazz == java.sql.Date.class) { 33 | v = new Timestamp( ((java.util.Date) value).getTime() ); 34 | } else if (vClazz == Long.class) { 35 | v = new Timestamp( (Long) value ); 36 | } else { 37 | v = (Timestamp) value; 38 | } 39 | pstmt.setTimestamp(index, v); 40 | } 41 | 42 | @Override 43 | public Object get(ResultSet rs, int index) throws SQLException { 44 | Timestamp v = rs.getTimestamp(index); 45 | return (v == null) ? null : new Date(v.getTime()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/function/GetDateFunction.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.function; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | import cn.devezhao.persist4j.dialect.Type; 5 | 6 | import java.text.SimpleDateFormat; 7 | import java.util.Calendar; 8 | 9 | /** 10 | * Usage: $getdate() 11 | * 12 | * @author Zhao Fangfang 13 | * @since 0.2, 2010-9-2 14 | * @version $Id: GetDateFunction.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 15 | */ 16 | public class GetDateFunction implements SqlFunction { 17 | 18 | @Override 19 | public String getToken() { 20 | return "getdate"; 21 | } 22 | 23 | @Override 24 | public Type getReturnType() { 25 | return FieldType.DATE; 26 | } 27 | 28 | @Override 29 | public String eval(Object[] arguments) { 30 | return new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/function/SqlFunction.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.function; 2 | 3 | import cn.devezhao.persist4j.dialect.Type; 4 | 5 | /** 6 | * SQL 函数 7 | * 8 | * @author FANGFANG ZHAO 9 | * @version 0.1, Apr 23, 2009 10 | */ 11 | public interface SqlFunction { 12 | 13 | /** 14 | * 函数名(不区分大小写) 15 | * 16 | * @return 17 | */ 18 | String getToken(); 19 | 20 | /** 21 | * 返回类型(兼容判断) 22 | * 23 | * @return 24 | */ 25 | Type getReturnType(); 26 | 27 | /** 28 | * 解析函数成为 SQL 29 | * 30 | * @param arguments 31 | * @return 32 | */ 33 | String eval(Object[] arguments); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/dialect/h2/H2Dialect.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.dialect.h2; 2 | 3 | import cn.devezhao.persist4j.dialect.FieldType; 4 | import cn.devezhao.persist4j.dialect.MySQL5Dialect; 5 | 6 | import java.sql.Types; 7 | 8 | /** 9 | * H2 with MySQL 10 | * 11 | * @author devezhao zhaofang123@gmail.com 12 | * @since 2019年11月28日 13 | */ 14 | public class H2Dialect extends MySQL5Dialect { 15 | private static final long serialVersionUID = 1212960786237010687L; 16 | 17 | public H2Dialect() { 18 | super(); 19 | registerColumnType(FieldType.DOUBLE.getMask(), "double(19)", Types.DOUBLE); 20 | } 21 | 22 | @Override 23 | public String getDialectName() { 24 | return "H2"; 25 | } 26 | 27 | @Override 28 | public boolean supportsFullText() { 29 | return Boolean.FALSE; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/ID.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.commons.ByteUtils; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.apache.commons.lang.Validate; 6 | import org.apache.commons.logging.Log; 7 | import org.apache.commons.logging.LogFactory; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * Id of record 13 | *
 14 |  * Using:
 15 |  *   # System.setProperty("org.qdss.persist.id", WeakIDGenerator.class.getName())
 16 |  * to set type of id
 17 |  * 
18 | * 19 | * @author FANGFANG ZHAO 20 | * @since 0.1, 06/12/08 21 | * @version $Id: ID.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 22 | */ 23 | public class ID implements Serializable { 24 | private static final long serialVersionUID = 5861261456599575527L; 25 | 26 | private static final Log LOG = LogFactory.getLog(ID.class); 27 | 28 | private static IDGenerator idGenerator; 29 | private static int idLength; 30 | static { 31 | String idClazz = StringUtils.defaultIfEmpty( 32 | System.getProperty("org.qdss.persist.id"), WeakIDGenerator.class.getName()); 33 | try { 34 | idGenerator = (IDGenerator) Class.forName(idClazz).getConstructor().newInstance(); 35 | } catch (Throwable ex) { 36 | LOG.error("Could't instance ID clazz: " + idClazz); 37 | } 38 | if (idGenerator == null) { 39 | idGenerator = new IDGenerator(); 40 | } 41 | idLength = idGenerator.getLength(); 42 | if (LOG.isInfoEnabled()) { 43 | LOG.warn("Using ID provider: " + idGenerator.getClass() + " (eg: " + idGenerator.generate(0) + ')'); 44 | } 45 | } 46 | 47 | public static final ID[] EMPTY_ID_ARRAY = new ID[0]; 48 | 49 | /** 50 | * @param typeCode 51 | * @return 52 | */ 53 | public static ID newId(int typeCode) { 54 | Validate.isTrue((typeCode > -1), "entity code must be or 0-999"); 55 | return new ID(idGenerator.generate(typeCode).toString()); 56 | } 57 | 58 | /** 59 | * @param id 60 | * @return 61 | */ 62 | public static boolean isId(Object id) { 63 | if (id instanceof ID) { 64 | return true; 65 | } 66 | 67 | if (id == null || StringUtils.isEmpty(id.toString()) 68 | || id.toString().length() != idLength) { 69 | return false; 70 | } 71 | 72 | return id.toString().charAt(3) == '-'; 73 | } 74 | 75 | /** 76 | * @param id 77 | * @return 78 | */ 79 | public static ID valueOf(String id) { 80 | if (!isId(id)) { 81 | throw new IllegalArgumentException("Invaild id character: " + id); 82 | } 83 | return (new ID(id)); 84 | } 85 | 86 | /** 87 | * @return 88 | */ 89 | public static IDGenerator getIDGenerator() { 90 | return idGenerator; 91 | } 92 | 93 | // ---------------------------------------------------------------------------- 94 | final private int entityCode; 95 | final private String id; 96 | 97 | private Object label; 98 | 99 | /** 100 | * Create a new ID 101 | * 102 | * @param id 103 | */ 104 | private ID(String id) { 105 | this.id = id.toLowerCase(); 106 | this.entityCode = Integer.parseInt(id.substring(0, 3)); 107 | } 108 | 109 | /** 110 | * @return 111 | */ 112 | public Integer getEntityCode() { 113 | return entityCode; 114 | } 115 | 116 | /** 117 | * @return 118 | */ 119 | public String toLiteral() { 120 | return id; 121 | } 122 | 123 | /** 124 | * @param label 125 | */ 126 | public void setLabel(Object label) { 127 | this.label = label; 128 | } 129 | 130 | /** 131 | * @return 132 | */ 133 | public String getLabel() { 134 | return label == null ? null : label.toString(); 135 | } 136 | 137 | /** 138 | * @return 139 | */ 140 | public Object getLabelRaw() { 141 | return label; 142 | } 143 | 144 | @Override 145 | public String toString() { 146 | return toLiteral(); 147 | } 148 | 149 | @Override 150 | public int hashCode() { 151 | return ByteUtils.hash(id.hashCode()); 152 | } 153 | 154 | @Override 155 | public boolean equals(Object obj) { 156 | if (!(obj instanceof ID)) { 157 | return false; 158 | } 159 | return obj.hashCode() == hashCode(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/IDGenerator.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.commons.identifier.UUIDHexGenerator; 4 | import org.apache.commons.lang.StringUtils; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * ID生成器 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, 06/13/08 13 | * @version $Id: IDGenerator.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 14 | */ 15 | public class IDGenerator extends UUIDHexGenerator { 16 | 17 | static char SEP = '-'; 18 | 19 | public IDGenerator() { 20 | super(SEP); 21 | } 22 | 23 | /** 24 | * ENTITY_CODE - IP - JVM - MO_TIME - LO_TIME - COUNT 25 | * 26 | * @param entityCode 27 | * @return 28 | */ 29 | public Serializable generate(Integer entityCode) { 30 | return new StringBuilder(getLength()).append( 31 | StringUtils.leftPad(entityCode + "", 3, '0')).append(SEP) 32 | .append(super.generate()); 33 | } 34 | 35 | @Override 36 | public Serializable generate() { 37 | return generate(0); 38 | } 39 | 40 | @Override 41 | public int getLength() { 42 | return 40; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/JdbcSupport.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.persist4j.DataAccessException; 4 | import cn.devezhao.persist4j.util.SqlHelper; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | 8 | import java.sql.*; 9 | 10 | /** 11 | * 12 | * @author FANGFANG ZHAO 13 | * @since 0.1, Feb 15, 2009 14 | * @version $Id: JdbcSupport.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 15 | */ 16 | public abstract class JdbcSupport { 17 | 18 | private static final Log LOG = LogFactory.getLog(JdbcSupport.class); 19 | 20 | private static final int TIMEOUT_DEFAULT = 5 * 60; 21 | 22 | private int timeout; 23 | 24 | /** 25 | */ 26 | protected JdbcSupport() { 27 | this(TIMEOUT_DEFAULT); 28 | } 29 | 30 | /** 31 | * @param timeout 32 | */ 33 | protected JdbcSupport(int timeout) { 34 | super(); 35 | this.timeout = timeout; 36 | } 37 | 38 | public int execute(StatementCallback callback) throws SQLException, DataAccessException { 39 | Connection connect = getConnection(); 40 | PreparedStatement pstmt = null; 41 | 42 | try { 43 | if (LOG.isDebugEnabled()) { 44 | LOG.debug("exec sql: " + callback.getSql()); 45 | } 46 | 47 | pstmt = connect.prepareStatement(callback.getSql()); 48 | pstmt.setQueryTimeout(getTimeout()); 49 | callback.doInParameters(pstmt); 50 | return pstmt.executeUpdate(); 51 | } catch (SQLException sqlex) { 52 | throw sqlex; 53 | } catch (Throwable unex) { 54 | throw new DataAccessException("Unexception on execute", unex); 55 | } finally { 56 | SqlHelper.close(pstmt); 57 | releaseConnection(connect); 58 | } 59 | } 60 | 61 | public int[] executeBatch(final String[] sqls) throws SQLException, DataAccessException { 62 | if (sqls.length == 1) { 63 | int exec = execute(new StatementCallback(){ 64 | @Override 65 | public String getSql() { 66 | return sqls[0]; 67 | } 68 | @Override 69 | public Object doInParameters(PreparedStatement pstmt) { 70 | return null; 71 | } 72 | }); 73 | return new int[] { exec }; 74 | } 75 | 76 | Connection connect = getConnection(); 77 | Statement stmt = null; 78 | int[] rowsAffected; 79 | try { 80 | stmt = connect.createStatement(); 81 | stmt.setQueryTimeout(getTimeout()); 82 | 83 | if (SqlHelper.supportsBatchUpdates(connect)) { 84 | for (String sql : sqls) { 85 | if (LOG.isDebugEnabled()) { 86 | LOG.debug("add sql to batch: " + sql); 87 | } 88 | 89 | stmt.addBatch(sql); 90 | } 91 | rowsAffected = stmt.executeBatch(); 92 | } else { 93 | rowsAffected = new int[sqls.length]; 94 | for (int i = 0; i < sqls.length; i++) { 95 | String crtSql = sqls[i]; 96 | 97 | if (LOG.isDebugEnabled()) { 98 | LOG.debug("exec sql(batch): " + crtSql); 99 | } 100 | 101 | if (!stmt.execute(crtSql)) { 102 | rowsAffected[i] = stmt.getUpdateCount(); 103 | } else { 104 | SqlHelper.close(stmt); 105 | throw new DataAccessException("Invalid batch SQL statement: " + crtSql); 106 | } 107 | } 108 | } 109 | } catch (SQLException sqlex) { 110 | throw sqlex; 111 | } catch (Throwable unex) { 112 | if (unex instanceof DataAccessException) { 113 | throw (DataAccessException) unex; 114 | } else { 115 | throw new DataAccessException("Unexception on executeBatch", unex); 116 | } 117 | } finally { 118 | SqlHelper.close(stmt); 119 | releaseConnection(connect); 120 | } 121 | return rowsAffected; 122 | } 123 | 124 | protected ResultSet nativeQuery(String sql) throws SQLException, DataAccessException { 125 | Connection connect = getConnection(); 126 | Statement stmt; 127 | ResultSet rs; 128 | 129 | try { 130 | stmt = connect.createStatement(); 131 | stmt.setQueryTimeout(getTimeout()); 132 | if (LOG.isDebugEnabled()) { 133 | LOG.debug("exec query: " + sql); 134 | } 135 | 136 | rs = stmt.executeQuery(sql); 137 | } catch (SQLException sqlex) { 138 | throw sqlex; 139 | } catch (Throwable unex) { 140 | throw new DataAccessException("Unexception on nativeQuery", unex); 141 | } 142 | return rs; 143 | } 144 | 145 | public void setTimeout(int timeout) { 146 | this.timeout = timeout; 147 | } 148 | 149 | public int getTimeout() { 150 | return timeout; 151 | } 152 | 153 | abstract protected Connection getConnection(); 154 | 155 | abstract protected void releaseConnection(Connection connect); 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/NullValue.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 空值 9 | * 10 | * @author zhaofang123@gmail.com 11 | * @since 12/28/2018 12 | */ 13 | public class NullValue implements Serializable { 14 | private static final long serialVersionUID = -6198308278862795848L; 15 | 16 | /** 17 | * @param value 18 | * @return 19 | */ 20 | public static boolean is(Object value) { 21 | return value instanceof NullValue; 22 | } 23 | 24 | /** 25 | * @param value 26 | * @return 27 | */ 28 | public static boolean isNull(Object value) { 29 | return value == null || is(value); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return StringUtils.EMPTY; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/PersistManagerFactoryImpl.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.persist4j.Filter; 4 | import cn.devezhao.persist4j.PersistManager; 5 | import cn.devezhao.persist4j.PersistManagerFactory; 6 | import cn.devezhao.persist4j.Query; 7 | import cn.devezhao.persist4j.dialect.Dialect; 8 | import cn.devezhao.persist4j.metadata.MetadataFactory; 9 | import cn.devezhao.persist4j.query.AjqlQuery; 10 | import cn.devezhao.persist4j.query.NativeQuery; 11 | import cn.devezhao.persist4j.query.NativeQueryImpl; 12 | 13 | import javax.sql.DataSource; 14 | 15 | /** 16 | * 持久化对象工厂 17 | * 18 | * @author FANGFANG ZHAO 19 | * @since 0.1, Feb 10, 2009 20 | * @version $Id: PersistManagerFactoryImpl.java 20 2009-02-10 03:35:10Z 21 | * zhaofang123@gmail.com $ 22 | */ 23 | public class PersistManagerFactoryImpl implements PersistManagerFactory { 24 | private static final long serialVersionUID = -3863550450762257322L; 25 | 26 | final private DataSource dataSource; 27 | 28 | final private Dialect dialect; 29 | final private MetadataFactory metadataFactory; 30 | final private SqlExecutorContext executorContext; 31 | 32 | public PersistManagerFactoryImpl(DataSource dataSource, Dialect dialect, 33 | MetadataFactory metadataFactory) { 34 | this.dataSource = dataSource; 35 | this.dialect = dialect; 36 | 37 | this.metadataFactory = metadataFactory; 38 | this.executorContext = new SqlExecutorContext(metadataFactory, dialect, dataSource); 39 | } 40 | 41 | @Override 42 | public DataSource getDataSource() { 43 | return dataSource; 44 | } 45 | 46 | @Override 47 | public Dialect getDialect() { 48 | return dialect; 49 | } 50 | 51 | @Override 52 | public MetadataFactory getMetadataFactory() { 53 | return metadataFactory; 54 | } 55 | 56 | @Override 57 | public SqlExecutorContext getSQLExecutorContext() { 58 | return executorContext; 59 | } 60 | 61 | @Override 62 | public PersistManager createPersistManager() { 63 | return (new PersistManagerImpl(this)); 64 | } 65 | 66 | @Override 67 | public Query createQuery(String ajql) { 68 | return createQuery(ajql, null); 69 | } 70 | 71 | @Override 72 | public Query createQuery(String ajql, Filter filter) { 73 | return new AjqlQuery(ajql, this, filter); 74 | } 75 | 76 | @Override 77 | public NativeQuery createNativeQuery(String sql) { 78 | return (new NativeQueryImpl(sql, this)); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/SqlExecutorContext.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.dialect.Dialect; 5 | import cn.devezhao.persist4j.metadata.MetadataFactory; 6 | import org.springframework.jdbc.datasource.DataSourceUtils; 7 | 8 | import javax.sql.DataSource; 9 | import java.io.Serializable; 10 | import java.sql.Connection; 11 | 12 | /** 13 | * Sql执行上下文信息 14 | * 15 | * @author FANGFANG ZHAO 16 | * @since 0.1, Mar 8, 2009 17 | * @version $Id: SqlExecutorContext.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 18 | */ 19 | public class SqlExecutorContext implements Serializable { 20 | private static final long serialVersionUID = 661188666290260734L; 21 | 22 | final private DataSource dataSource; 23 | final private MetadataFactory metadataFactory; 24 | final private Dialect dialect; 25 | 26 | public SqlExecutorContext(MetadataFactory metadataFactory, Dialect dialect, 27 | DataSource dataSource) { 28 | this.metadataFactory = metadataFactory; 29 | this.dialect = dialect; 30 | this.dataSource = dataSource; 31 | } 32 | 33 | public Dialect getDialect() { 34 | return dialect; 35 | } 36 | 37 | public Entity getEntity(String tname) { 38 | return metadataFactory.getEntity(tname); 39 | } 40 | 41 | public Entity getEntity(int tcode) { 42 | return metadataFactory.getEntity(tcode); 43 | } 44 | 45 | public Connection getConnection() { 46 | return DataSourceUtils.getConnection(getDataSource()); 47 | } 48 | 49 | public DataSource getDataSource() { 50 | return dataSource; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/StatementCallback.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import java.sql.PreparedStatement; 4 | import java.sql.SQLException; 5 | 6 | /** 7 | * 语句回调 8 | * 9 | * @author FANGFANG ZHAO 10 | * @since 0.1, Feb 15, 2009 11 | * @version $Id: StatementCallback.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 12 | */ 13 | public interface StatementCallback { 14 | 15 | String getSql(); 16 | 17 | Object doInParameters(PreparedStatement pstmt) throws SQLException; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/engine/WeakIDGenerator.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 弱ID生成器,只有20位长度 9 | * 10 | * @author Zhao Fangfang 11 | * @since 0.2, 2010-8-11 12 | * @version $Id: WeakIDGenerator.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public class WeakIDGenerator extends IDGenerator { 15 | 16 | /** 17 | * ENTITY_CODE - MO_TIME LO_TIME COUNT 18 | */ 19 | @Override 20 | public Serializable generate(Integer entityCode) { 21 | return new StringBuilder(getLength()).append( 22 | StringUtils.leftPad(entityCode + StringUtils.EMPTY, 3, '0')).append(SEP).append( 23 | format(getMoTime())).append(format(getLoTime())).append(format(getCount())) 24 | .toString(); 25 | } 26 | 27 | @Override 28 | public int getLength() { 29 | return 20; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/JdbcException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception; 2 | 3 | import cn.devezhao.persist4j.DataAccessException; 4 | 5 | import java.sql.SQLException; 6 | 7 | /** 8 | * JDBC异常 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 11, 2009 12 | * @version $Id: JDBCException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public class JdbcException extends DataAccessException { 15 | private static final long serialVersionUID = -6444431350667265965L; 16 | 17 | private SQLException sqlex; 18 | private String sql; 19 | 20 | public JdbcException(String message, Throwable ex) { 21 | super(message, ex); 22 | } 23 | 24 | public JdbcException(String message, SQLException root) { 25 | super(message, root); 26 | sqlex = root; 27 | } 28 | 29 | public JdbcException(String message, SQLException root, String sql) { 30 | super(message, root); 31 | this.sqlex = root; 32 | this.sql = sql; 33 | } 34 | 35 | /** 36 | * Get the SQLState of the underlying SQLException. 37 | * 38 | * @see java.sql.SQLException 39 | * @return String 40 | */ 41 | public String getSQLState() { 42 | return sqlex.getSQLState(); 43 | } 44 | 45 | /** 46 | * Get the errorCode of the underlying SQLException. 47 | * 48 | * @see java.sql.SQLException 49 | * @return int the error code 50 | */ 51 | public int getErrorCode() { 52 | return sqlex.getErrorCode(); 53 | } 54 | 55 | /** 56 | * Get the underlying SQLException. 57 | * 58 | * @return SQLException 59 | */ 60 | public SQLException getSQLException() { 61 | return sqlex; 62 | } 63 | 64 | /** 65 | * Get the actual SQL statement that caused the exception (may be null) 66 | */ 67 | public String getSQL() { 68 | return sql; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return new StringBuilder() 74 | .append("\n** SQL Error ************************************************************************") 75 | .append("\nSQL: ").append(sql) 76 | .append("\nCategory: ").append(getClass()) 77 | .append("\nVendorError: ").append(getErrorCode()) 78 | .append("\nSQLState: ").append(getSQLException().getSQLState()) 79 | .append("\nCause: ").append(sqlex) 80 | .append("\nMessage: ").append(getMessage()) 81 | .toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/SqlExceptionConverter.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception; 2 | 3 | import cn.devezhao.persist4j.exception.jdbc.ConstraintViolationException; 4 | import cn.devezhao.persist4j.exception.jdbc.DataTruncationException; 5 | import cn.devezhao.persist4j.exception.jdbc.GenericJdbcException; 6 | import cn.devezhao.persist4j.exception.jdbc.LockAcquisitionException; 7 | import cn.devezhao.persist4j.exception.jdbc.SqlSyntaxException; 8 | 9 | import java.sql.DataTruncation; 10 | import java.sql.SQLException; 11 | import java.sql.SQLIntegrityConstraintViolationException; 12 | import java.sql.SQLSyntaxErrorException; 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | /** 17 | * 将Sql异常转换至清晰的异常类型 18 | * 19 | * @author FANGFANG ZHAO 20 | * @since 0.1, 03/19/08 21 | * @version $Id: SqlExceptionConverter.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 22 | */ 23 | public class SqlExceptionConverter { 24 | 25 | private static final Set SQL_GRAMMAR_CATEGORIES = new HashSet<>(); 26 | private static final Set DATA_CATEGORIES = new HashSet<>(); 27 | private static final Set INTEGRITY_VIOLATION_CATEGORIES = new HashSet<>(); 28 | private static final Set CONNECTION_CATEGORIES = new HashSet<>(); 29 | 30 | // error code 31 | static { 32 | SQL_GRAMMAR_CATEGORIES.add("07"); 33 | SQL_GRAMMAR_CATEGORIES.add("37"); 34 | SQL_GRAMMAR_CATEGORIES.add("42"); 35 | SQL_GRAMMAR_CATEGORIES.add("65"); 36 | SQL_GRAMMAR_CATEGORIES.add("S0"); 37 | SQL_GRAMMAR_CATEGORIES.add("20"); 38 | 39 | DATA_CATEGORIES.add("22"); 40 | DATA_CATEGORIES.add("21"); 41 | DATA_CATEGORIES.add("02"); 42 | 43 | INTEGRITY_VIOLATION_CATEGORIES.add("23"); 44 | INTEGRITY_VIOLATION_CATEGORIES.add("27"); 45 | INTEGRITY_VIOLATION_CATEGORIES.add("44"); 46 | 47 | CONNECTION_CATEGORIES.add("08"); 48 | } 49 | 50 | /** 51 | */ 52 | private SqlExceptionConverter() { } 53 | 54 | /** 55 | * Converter jdbc exception 56 | * 57 | * @param sqlex 58 | * @param message 59 | * @param sql 60 | * @return 61 | */ 62 | public static JdbcException convert(SQLException sqlex, String message, String sql) { 63 | String stateCode = sqlex.getSQLState(); 64 | 65 | if (stateCode != null && stateCode.length() >= 2) { 66 | String classCode = stateCode.substring(0, 2); 67 | 68 | if (SQL_GRAMMAR_CATEGORIES.contains(classCode)) { 69 | if (sqlex instanceof SQLSyntaxErrorException 70 | && sqlex.getLocalizedMessage().contains("this is incompatible with sql_mode=only_full_group_by")) { 71 | message = "INCOMPATIBLE SQLMODE(ONLY_FULL_GROUP_BY)"; 72 | } 73 | return new SqlSyntaxException(message, sqlex, sql); 74 | } else if (INTEGRITY_VIOLATION_CATEGORIES.contains(classCode) 75 | || sqlex instanceof SQLIntegrityConstraintViolationException) { 76 | return new ConstraintViolationException(message, sqlex, sql); 77 | } 78 | } 79 | 80 | if ("40001".equals(stateCode)) { 81 | return new LockAcquisitionException(message, sqlex, sql); 82 | } 83 | 84 | if ("61000".equals(stateCode)) { 85 | // oracle sql-state code for deadlock 86 | return new LockAcquisitionException(message, sqlex, sql); 87 | } 88 | 89 | if (sqlex instanceof DataTruncation) { 90 | return new DataTruncationException(message, sqlex, sql); 91 | } 92 | 93 | return handledNonSpecificException(sqlex, message, sql); 94 | } 95 | 96 | /** 97 | * 违反约束类异常?如唯一冲突 98 | * 99 | * @param sqlex 100 | * @return 101 | */ 102 | public static boolean isConstraintViolationException(SQLException sqlex) { 103 | String stateCode = sqlex.getSQLState(); 104 | if (stateCode != null && stateCode.length() >= 2) { 105 | String classCode = stateCode.substring(0, 2); 106 | return INTEGRITY_VIOLATION_CATEGORIES.contains(classCode) 107 | || sqlex instanceof SQLIntegrityConstraintViolationException; 108 | } 109 | return false; 110 | } 111 | 112 | /** 113 | * non-specific sql exception 114 | * 115 | * @param sqlex 116 | * @param message 117 | * @param sql 118 | * @return 119 | */ 120 | private static JdbcException handledNonSpecificException(SQLException sqlex, 121 | String message, String sql) { 122 | return new GenericJdbcException(message, sqlex, sql); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/SqlWarningException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception; 2 | 3 | import cn.devezhao.persist4j.DataAccessException; 4 | 5 | import java.sql.SQLWarning; 6 | 7 | /** 8 | * Sql警告类的异常 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 17, 2009 12 | * @version $Id: SqlWarningException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public class SqlWarningException extends DataAccessException { 15 | private static final long serialVersionUID = -4242858921986055820L; 16 | 17 | public SqlWarningException(String message, SQLWarning ex) { 18 | super(message, ex); 19 | } 20 | 21 | public SQLWarning SQLWarning() { 22 | return (SQLWarning) getCause(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/jdbc/ConstraintViolationException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception.jdbc; 2 | 3 | import cn.devezhao.persist4j.exception.JdbcException; 4 | 5 | import java.sql.SQLException; 6 | 7 | 8 | /** 9 | * Implementation of JDBCException indicating that the requested DML operation 10 | * resulted in a violation of a defined integrity constraint. 11 | * 12 | * @author FANGFANG ZHAO 13 | * @since 0.1, 03/19/08 14 | * @version $Id: ConstraintViolationException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 15 | */ 16 | public class ConstraintViolationException extends JdbcException { 17 | private static final long serialVersionUID = -6763398332806161179L; 18 | 19 | private String constraintName; 20 | 21 | public ConstraintViolationException(String message, SQLException root, 22 | String constraintName) { 23 | super(message, root); 24 | this.constraintName = constraintName; 25 | } 26 | 27 | public ConstraintViolationException(String message, SQLException root, 28 | String sql, String constraintName) { 29 | super(message, root, sql); 30 | this.constraintName = constraintName; 31 | } 32 | 33 | /** 34 | * Returns the name of the violated constraint, if known. 35 | * 36 | * @return The name of the violated constraint, or null if not known. 37 | */ 38 | public String getConstraintName() { 39 | return constraintName; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/jdbc/DataTruncationException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception.jdbc; 2 | 3 | import cn.devezhao.persist4j.exception.JdbcException; 4 | 5 | import java.sql.SQLException; 6 | 7 | /** 8 | * 9 | * @author FANGFANG ZHAO 10 | * @since 1.7.3, 10/20/2023 11 | */ 12 | public class DataTruncationException extends JdbcException { 13 | 14 | public DataTruncationException(String message, SQLException root) { 15 | super(message, root); 16 | } 17 | 18 | public DataTruncationException(String message, SQLException root, String sql) { 19 | super(message, root, sql); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/jdbc/GenericJdbcException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception.jdbc; 2 | 3 | import cn.devezhao.persist4j.exception.JdbcException; 4 | 5 | import java.sql.SQLException; 6 | 7 | 8 | /** 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, 03/06/08 12 | * @version $Id: GenericJDBCException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public class GenericJdbcException extends JdbcException { 15 | private static final long serialVersionUID = 3557785158242479097L; 16 | 17 | public GenericJdbcException(String message, SQLException root) { 18 | super(message, root); 19 | } 20 | 21 | public GenericJdbcException(String message, SQLException root, String sql) { 22 | super(message, root, sql); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/jdbc/LockAcquisitionException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception.jdbc; 2 | 3 | import cn.devezhao.persist4j.exception.JdbcException; 4 | 5 | import java.sql.SQLException; 6 | 7 | 8 | /** 9 | * Implementation of JDBCException indicating a problem acquiring lock on the 10 | * database. 11 | * 12 | * @author FANGFANG ZHAO 13 | * @since 0.1, 03/06/08 14 | * @version $Id: LockAcquisitionException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 15 | */ 16 | public class LockAcquisitionException extends JdbcException { 17 | private static final long serialVersionUID = 7645330533080871391L; 18 | 19 | public LockAcquisitionException(String message, SQLException root) { 20 | super(message, root); 21 | } 22 | 23 | public LockAcquisitionException(String message, SQLException root, 24 | String sql) { 25 | super(message, root, sql); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/exception/jdbc/SqlSyntaxException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.exception.jdbc; 2 | 3 | import cn.devezhao.persist4j.exception.JdbcException; 4 | 5 | import java.sql.SQLException; 6 | 7 | 8 | /** 9 | * Sql语法错误异常 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, 03/06/08 13 | * @version $Id: SqlSyntaxException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 14 | */ 15 | public class SqlSyntaxException extends JdbcException { 16 | private static final long serialVersionUID = 7095739972833914851L; 17 | 18 | public SqlSyntaxException(String message, SQLException root) { 19 | super(message, root); 20 | } 21 | 22 | public SqlSyntaxException(String message, SQLException root, String sql) { 23 | super(message, root, sql); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/BaseMeta.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Base meta object 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Jan 20, 2009 12 | * @version $Id: BaseMeta.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 13 | */ 14 | public interface BaseMeta extends Serializable { 15 | 16 | /** 17 | * 获取名称 18 | * 19 | * @return 20 | */ 21 | String getName(); 22 | 23 | /** 24 | * 获取物理名称 25 | * 26 | * @return 27 | */ 28 | String getPhysicalName(); 29 | 30 | /** 31 | * 获取描述 32 | * 33 | * @return 34 | */ 35 | String getDescription(); 36 | 37 | /** 38 | * 是否可创建 39 | * 40 | * @return 41 | */ 42 | boolean isCreatable(); 43 | 44 | /** 45 | * 是否可更新 46 | * 47 | * @return 48 | */ 49 | boolean isUpdatable(); 50 | 51 | /** 52 | * 是否可查询 53 | * 54 | * @return 55 | */ 56 | boolean isQueryable(); 57 | 58 | /** 59 | * 扩展属性(便于实现自定义属性) 60 | * 61 | * @return 62 | */ 63 | JSONObject getExtraAttrs(); 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/BaseMetaObject.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | /** 6 | * 元数据基础 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Jan 20, 2009 10 | * @version $Id: BaseMetaObject.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public abstract class BaseMetaObject implements BaseMeta { 13 | private static final long serialVersionUID = -439042640413431557L; 14 | 15 | final private String name; 16 | final private String physicalName; 17 | final private String description; 18 | final private JSONObject extraAttrs; 19 | 20 | final private boolean creatable; 21 | final private boolean updatable; 22 | final private boolean queryable; 23 | 24 | /** 25 | * @param name 26 | * @param physicalName 27 | * @param description 28 | * @param extraAttrs 29 | * @param creatable 30 | * @param updatable 31 | * @param queryable 32 | */ 33 | public BaseMetaObject(String name, String physicalName, String description, JSONObject extraAttrs, 34 | boolean creatable, boolean updatable, boolean queryable) { 35 | this.name = name; 36 | this.physicalName = physicalName; 37 | this.description = description; 38 | this.extraAttrs = extraAttrs; 39 | this.creatable = creatable; 40 | this.updatable = updatable; 41 | this.queryable = queryable; 42 | } 43 | 44 | @Override 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | @Override 50 | public String getPhysicalName() { 51 | return physicalName; 52 | } 53 | 54 | @Override 55 | public String getDescription() { 56 | return description; 57 | } 58 | 59 | @Override 60 | public JSONObject getExtraAttrs() { 61 | return extraAttrs == null ? null : (JSONObject) extraAttrs.clone(); 62 | } 63 | 64 | @Override 65 | public boolean isCreatable() { 66 | return creatable; 67 | } 68 | 69 | @Override 70 | public boolean isUpdatable() { 71 | return updatable; 72 | } 73 | 74 | @Override 75 | public boolean isQueryable() { 76 | return queryable; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return String.format("<%s,%s>@%s", name, physicalName, Integer.toHexString(super.hashCode())); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/CascadeModel.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 级联删除模式 8 | * 9 | * @author FANGFANG ZHAO 10 | * @since 0.1, Feb 15, 2009 11 | * @version $Id: CascadeModel.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 12 | */ 13 | public enum CascadeModel { 14 | 15 | /** 16 | * 级联删除 17 | */ 18 | Delete, 19 | /** 20 | * 移除链接 21 | */ 22 | RemoveLinks, 23 | /** 24 | * 忽略,啥都不干 25 | */ 26 | Ignore; 27 | 28 | private static final Map NAMED = new HashMap<>(); 29 | static { 30 | NAMED.put("delete", Delete); 31 | NAMED.put("remove-links", RemoveLinks); 32 | NAMED.put("removelinks", RemoveLinks); 33 | NAMED.put("ignore", Ignore); 34 | } 35 | 36 | /** 37 | * @param model 38 | * @return 39 | */ 40 | public static CascadeModel parse(String model) { 41 | CascadeModel cm = NAMED.get(model.toLowerCase()); 42 | if (cm != null) { 43 | return cm; 44 | } 45 | throw new MetadataException("No CascadeModel found: " + model); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/MetadataException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | 5 | /** 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, Feb 4, 2009 8 | * @version $Id: MetadataException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public class MetadataException extends PersistException { 11 | private static final long serialVersionUID = -2308505098712378613L; 12 | 13 | public MetadataException(String message) { 14 | super(message); 15 | } 16 | 17 | public MetadataException(String message, Throwable ex) { 18 | super(message, ex); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/MetadataFactory.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 2, 2009 10 | * @version $Id: MetadataFactory.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public interface MetadataFactory extends Serializable { 13 | 14 | Entity getEntity(String aName); 15 | 16 | Entity getEntity(int aType); 17 | 18 | boolean containsEntity(int aType); 19 | 20 | Entity[] getEntities(); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/MissingMetaExcetion.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | /** 4 | * 实体或字段未找到(可能已经删除) 5 | * 6 | * @author devezhao 7 | * @since 2020/12/19 8 | */ 9 | public class MissingMetaExcetion extends MetadataException { 10 | 11 | public MissingMetaExcetion(String message) { 12 | super(message); 13 | } 14 | 15 | public MissingMetaExcetion(String field, String entity) { 16 | super("No such field [ " + field + " ] in entity [ " + entity + " ]"); 17 | } 18 | 19 | public MissingMetaExcetion(String message, Throwable ex) { 20 | super(message, ex); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/impl/AnyEntity.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata.impl; 2 | 3 | /** 4 | * 任意引用字段指向的实体 5 | * 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, 2010-6-28 8 | * @version $Id: AnyEntity.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public final class AnyEntity extends EntityImpl { 11 | private static final long serialVersionUID = 1666508270744579952L; 12 | 13 | /** 14 | * 任意引用标识 15 | */ 16 | public static final String FLAG = "*"; 17 | 18 | protected AnyEntity() { 19 | super(null, null, null, null, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, 20 | 0, null, Boolean.TRUE); 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/metadata/impl/FieldImpl.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata.impl; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.Field; 5 | import cn.devezhao.persist4j.dialect.Type; 6 | import cn.devezhao.persist4j.metadata.BaseMetaObject; 7 | import cn.devezhao.persist4j.metadata.CascadeModel; 8 | import com.alibaba.fastjson.JSONObject; 9 | 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | /** 14 | * @author FANGFANG ZHAO 15 | * @since 0.1, Feb 4, 2009 16 | * @version $Id: FieldImpl.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 17 | */ 18 | public class FieldImpl extends BaseMetaObject implements Field, Cloneable { 19 | private static final long serialVersionUID = 1702329731097027085L; 20 | 21 | final private static Entity[] EMPTY_ENTITY_ARRAY = new Entity[0]; 22 | 23 | final private Entity ownEntity; 24 | final private Type type; 25 | final private int maxLength; 26 | final private CascadeModel cascadeModel; 27 | final private boolean nullable; 28 | final private boolean repeatable; 29 | final private boolean autoValue; 30 | final private int decimalScale; 31 | final private Object defaultValue; 32 | 33 | private Set referenceSet = new HashSet<>(); 34 | 35 | public FieldImpl(String name, String physicalName, String description, JSONObject extraAttrs, 36 | boolean creatable, boolean updatable, boolean queryable, 37 | Entity ownEntity, Type type, int maxLength, CascadeModel cascadeModel, 38 | boolean nullable, boolean repeatable, boolean autoValue, int decimalScale, Object defaultValue) { 39 | super(name, physicalName, description, extraAttrs, creatable, updatable, queryable); 40 | this.ownEntity = ownEntity; 41 | this.type = type; 42 | this.maxLength = maxLength; 43 | this.cascadeModel = cascadeModel; 44 | this.nullable = nullable; 45 | this.repeatable = repeatable; 46 | this.autoValue = autoValue; 47 | this.decimalScale = decimalScale; 48 | this.defaultValue = defaultValue; 49 | } 50 | 51 | protected FieldImpl(Field c, Entity ownEntity) { 52 | this(c.getName(), c.getPhysicalName(), c.getDescription(), c.getExtraAttrs(), 53 | c.isCreatable(), c.isUpdatable(), c.isQueryable(), 54 | ownEntity, c.getType(), c.getMaxLength(), c.getCascadeModel(), 55 | c.isNullable(), c.isRepeatable(), c.isAutoValue(), c.getDecimalScale(), c.getDefaultValue()); 56 | } 57 | 58 | @Override 59 | public Entity getOwnEntity() { 60 | return ownEntity; 61 | } 62 | 63 | @Override 64 | public Type getType() { 65 | return type; 66 | } 67 | 68 | @Override 69 | public int getMaxLength() { 70 | return maxLength; 71 | } 72 | 73 | @Override 74 | public CascadeModel getCascadeModel() { 75 | return cascadeModel; 76 | } 77 | 78 | @Override 79 | public boolean isNullable() { 80 | return nullable; 81 | } 82 | 83 | @Override 84 | public boolean isRepeatable() { 85 | return repeatable; 86 | } 87 | 88 | @Override 89 | public boolean isAutoValue() { 90 | return autoValue; 91 | } 92 | 93 | @Override 94 | public int getDecimalScale() { 95 | return decimalScale; 96 | } 97 | 98 | 99 | @Override 100 | public Object getDefaultValue() { 101 | return defaultValue; 102 | } 103 | 104 | @Override 105 | public Entity[] getReferenceEntities() { 106 | if (referenceSet.isEmpty()) { 107 | return EMPTY_ENTITY_ARRAY; 108 | } 109 | return referenceSet.toArray(new Entity[0]); 110 | } 111 | 112 | @Override 113 | public Entity getReferenceEntity() { 114 | Entity[] e = getReferenceEntities(); 115 | return e.length == 0 ? null : e[0]; 116 | } 117 | 118 | @Override 119 | public int hashCode() { 120 | return (ownEntity.getName() + "#" + getName()).hashCode(); 121 | } 122 | 123 | @Override 124 | public boolean equals(Object obj) { 125 | if (obj == this) { 126 | return true; 127 | } 128 | if (!(obj instanceof FieldImpl)) { 129 | return false; 130 | } 131 | return obj.hashCode() == hashCode(); 132 | } 133 | 134 | @Override 135 | public String toString() { 136 | return (ownEntity.getName() + "#" + getName()).toUpperCase(); 137 | // return new StringBuilder().append("<").append( 138 | // ownEntity.getName()).append("#").append(getName()).append( 139 | // "(").append(getType()).append(",").append(getMaxLength()).append(")>@").append(super.toString()).toString(); 140 | } 141 | 142 | @Override 143 | public Object clone() throws CloneNotSupportedException { 144 | FieldImpl clone = (FieldImpl) super.clone(); 145 | clone.referenceSet = new HashSet<>(this.referenceSet); 146 | return clone; 147 | } 148 | 149 | /** 150 | * @param entity 151 | */ 152 | protected void addReference(Entity entity) { 153 | referenceSet.add(entity); 154 | ((EntityImpl) entity).addReferenceTo(this); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/AjqlQuery.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.Record; 4 | import cn.devezhao.persist4j.*; 5 | import cn.devezhao.persist4j.query.compiler.QueryCompiler; 6 | import cn.devezhao.persist4j.query.compiler.SelectItem; 7 | 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * Ajql query 14 | * 15 | * @author FANGFANG ZHAO 16 | * @since 0.1, Feb 10, 2009 17 | * @version $Id: StandardQuery.java 23 2009-02-15 12:16:17Z 18 | * zhaofang123@gmail.com $ 19 | */ 20 | public class AjqlQuery extends BaseQuery implements Query { 21 | private static final long serialVersionUID = -2539834203845429816L; 22 | 23 | final private String ajql; 24 | transient private PersistManagerFactory managerFactory; 25 | private Filter filter; 26 | 27 | private Map inParameters = new HashMap<>(); 28 | 29 | private QueryCompiler queryCompiler; 30 | private Result result; 31 | 32 | public AjqlQuery(String ajql, PersistManagerFactory managerFactory) { 33 | this(ajql, managerFactory, null); 34 | } 35 | 36 | public AjqlQuery(String ajql, PersistManagerFactory managerFactory, Filter filter) { 37 | this.ajql = ajql; 38 | this.managerFactory = managerFactory; 39 | this.filter = filter; 40 | } 41 | 42 | @Override 43 | public Query setParameter(int position, Object value) { 44 | return setParameter(position + "", value); 45 | } 46 | 47 | @Override 48 | public Query setParameter(String name, Object value) { 49 | inParameters.put(name, value); 50 | return this; 51 | } 52 | 53 | @Override 54 | public Query setFilter(Filter filter) { 55 | this.filter = filter; 56 | return this; 57 | } 58 | 59 | @Override 60 | public Result result() { 61 | if (result == null) { 62 | result = new AjqlResultImpl(this); 63 | } 64 | return result; 65 | } 66 | 67 | @Override 68 | public Object[] unique() { 69 | return result().unique(); 70 | } 71 | 72 | @Override 73 | public Object[][] array() { 74 | return result().array(); 75 | } 76 | 77 | @Override 78 | public List list() { 79 | return result().list(); 80 | } 81 | 82 | @Override 83 | public Record record() { 84 | return result().record(); 85 | } 86 | 87 | @Override 88 | public Query reset() { 89 | result().reset(); 90 | return this; 91 | } 92 | 93 | @Override 94 | public Entity getRootEntity() { 95 | compileQueryIfNeed(); 96 | return queryCompiler.getRootEntity(); 97 | } 98 | 99 | @Override 100 | public SelectItem[] getSelectItems() { 101 | compileQueryIfNeed(); 102 | return queryCompiler.getSelectItems(); 103 | } 104 | 105 | private void compileQueryIfNeed() { 106 | if (queryCompiler != null) { 107 | return; 108 | } 109 | queryCompiler = new QueryCompiler(this.ajql); 110 | queryCompiler.compile(managerFactory.getSQLExecutorContext(), this.filter); 111 | } 112 | 113 | // --------------------------------------------------------------------- 114 | 115 | protected PersistManagerFactory getPersistManagerFactory() { 116 | return managerFactory; 117 | } 118 | 119 | protected QueryCompiler getQueryCompiler() { 120 | return queryCompiler; 121 | } 122 | 123 | protected Map getInParameters() { 124 | return inParameters; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/BaseQuery.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | /** 4 | * 5 | * 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, May 25, 2009 8 | * @version $Id: BaseQuery.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public abstract class BaseQuery implements IQuery { 11 | private static final long serialVersionUID = -5599409110546399955L; 12 | 13 | private int firstResult; 14 | private int maxResults; 15 | private int timeout; 16 | private int slowLoggerTime; 17 | 18 | protected int limit, offset; 19 | 20 | @Override 21 | public int getFirstResult() { 22 | return firstResult; 23 | } 24 | 25 | @Override 26 | @SuppressWarnings("unchecked") 27 | public T setFirstResult(int firstResult) { 28 | this.firstResult = firstResult; 29 | return (T) this; 30 | } 31 | 32 | @Override 33 | public int getMaxResults() { 34 | return maxResults; 35 | } 36 | 37 | @Override 38 | @SuppressWarnings("unchecked") 39 | public T setMaxResults(int maxResults) { 40 | this.maxResults = maxResults; 41 | return (T) this; 42 | } 43 | 44 | @Override 45 | public int getTimeout() { 46 | return timeout; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public T setTimeout(int timeout) { 52 | this.timeout = timeout; 53 | return (T) this; 54 | } 55 | 56 | @Override 57 | public int getSlowLoggerTime() { 58 | return slowLoggerTime; 59 | } 60 | 61 | @Override 62 | @SuppressWarnings("unchecked") 63 | public T setSlowLoggerTime(int loggerTime) { 64 | this.slowLoggerTime = loggerTime; 65 | return (T) this; 66 | } 67 | 68 | @Override 69 | public T setLimit(int limit) { 70 | return setLimit(limit, 0); 71 | } 72 | 73 | @Override 74 | @SuppressWarnings("unchecked") 75 | public T setLimit(int limit, int offset) { 76 | this.limit = limit; 77 | this.offset = offset; 78 | return (T) this; 79 | } 80 | 81 | @Override 82 | public T setParameter(int position, Object value) { 83 | throw new UnsupportedOperationException(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/IQuery.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 查询根接口 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, May 25, 2009 10 | * @version $Id: IQuery.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public interface IQuery extends Serializable { 13 | 14 | T setFirstResult(int firstResult); 15 | 16 | int getFirstResult(); 17 | 18 | T setMaxResults(int maxResults); 19 | 20 | int getMaxResults(); 21 | 22 | T setTimeout(int timeout); 23 | 24 | int getTimeout(); 25 | 26 | T setSlowLoggerTime(int loggerTime); 27 | 28 | int getSlowLoggerTime(); 29 | 30 | T setLimit(int limit); 31 | 32 | T setLimit(int limit, int offset); 33 | 34 | T setParameter(int position, Object value); 35 | 36 | Object[] unique(); 37 | 38 | Object[][] array(); 39 | 40 | T reset(); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/NativeQuery.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.dialect.Type; 4 | 5 | /** 6 | * 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, May 25, 2009 10 | * @version $Id: NativeQuery.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public interface NativeQuery extends IQuery { 13 | 14 | NativeQuery setInParameterType(Type... fTypes); 15 | 16 | NativeQuery setReturnType(Type... fTypes); 17 | 18 | @Override 19 | NativeQuery reset(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/QueryException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | 5 | /** 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, Feb 16, 2009 8 | * @version $Id: QueryException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public class QueryException extends PersistException { 11 | private static final long serialVersionUID = -5585083095838431318L; 12 | 13 | public QueryException(String message) { 14 | super(message); 15 | } 16 | 17 | public QueryException(String message, Throwable ex) { 18 | super(message, ex); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/QueryedRecord.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.Field; 5 | import cn.devezhao.persist4j.dialect.FieldType; 6 | import cn.devezhao.persist4j.engine.ID; 7 | import cn.devezhao.persist4j.engine.SqlExecutorContext; 8 | import cn.devezhao.persist4j.engine.StandardRecord; 9 | import cn.devezhao.persist4j.query.compiler.QueryCompiler; 10 | import cn.devezhao.persist4j.query.compiler.SelectItem; 11 | import cn.devezhao.persist4j.record.FieldValueException; 12 | import cn.devezhao.persist4j.util.CaseInsensitiveMap; 13 | import org.apache.commons.logging.Log; 14 | import org.apache.commons.logging.LogFactory; 15 | 16 | import java.util.Map; 17 | 18 | /** 19 | * 查询出的记录 20 | * 21 | * @author FANGFANG ZHAO 22 | * @since 0.1, Mar 8, 2009 23 | * @version $Id: CapriciousRecord.java 121 2016-01-08 04:07:07Z zhaofang123@gmail.com $ 24 | */ 25 | public class QueryedRecord extends StandardRecord { 26 | private static final long serialVersionUID = 5113799283331109208L; 27 | 28 | private static final Log LOG = LogFactory.getLog(QueryedRecord.class); 29 | 30 | private final Map idLabel = new CaseInsensitiveMap<>(); 31 | private SelectItem[] selectItems; 32 | 33 | /** 34 | * for Serializable 35 | */ 36 | protected QueryedRecord() { 37 | super(); 38 | } 39 | 40 | protected QueryedRecord(Entity entity, SqlExecutorContext context) { 41 | super(entity, null); 42 | } 43 | 44 | public void setSelectItems(SelectItem[] selectItems) { 45 | this.selectItems = selectItems.clone(); 46 | } 47 | 48 | public SelectItem[] getSelectItems() { 49 | return selectItems.clone(); 50 | } 51 | 52 | @Override 53 | protected void setObject(String key, Object value) { 54 | Entity e = getEntity(); 55 | if (e.containsField(key)) { 56 | try { 57 | super.setObject(key, value); 58 | } catch (FieldValueException ex) { 59 | LOG.warn("QueryedRecord#setObject error : " + key + "=" + value, ex); 60 | } 61 | return; 62 | } 63 | 64 | if (key.charAt(0) == QueryCompiler.NAME_FIELD_PREFIX) { 65 | key = key.substring(1); 66 | ID id = getID(key); 67 | if (id != null) { 68 | id.setLabel(value); 69 | } else { 70 | idLabel.put(key, value); 71 | } 72 | } else { 73 | recordMap.put(key, value); 74 | } 75 | } 76 | 77 | @Override 78 | protected Object getObject(String key, Class clazz) { 79 | Entity e = getEntity(); 80 | if (e.containsField(key)) { 81 | return super.getObject(key, clazz); 82 | } 83 | return recordMap.get(key); 84 | } 85 | 86 | @Override 87 | protected void checkReferenceValue(Field field, Object value) { 88 | if (field.getType() == FieldType.ANY_REFERENCE) return; 89 | super.checkReferenceValue(field, value); 90 | } 91 | 92 | /** 93 | * 完成后整理数据结构 94 | */ 95 | protected void completeAfter() { 96 | if (idLabel.isEmpty()) { 97 | return; 98 | } 99 | 100 | for (Map.Entry e : idLabel.entrySet()) { 101 | ID id = getID(e.getKey()); 102 | if (id != null) { 103 | id.setLabel(e.getValue()); 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/Result.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.Record; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * 查询结果集 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, Feb 10, 2009 13 | * @version $Id: Result.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 14 | */ 15 | public interface Result extends Serializable { 16 | 17 | Object[] unique(); 18 | 19 | Record record(); 20 | 21 | List list(); 22 | 23 | Object[][] array(); 24 | 25 | Result reset(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/SlowLogger.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | 6 | /** 7 | * 慢查询记录 8 | * 9 | * @author Zhao Fangfang 10 | * @since 2011-4-11 11 | * @version $Id: SlowLogger.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 12 | */ 13 | public class SlowLogger { 14 | 15 | private static final Log LOG = LogFactory.getLog(SlowLogger.class); 16 | 17 | private static final ThreadLocal QUERY_START = new ThreadLocal<>(); 18 | 19 | /** 20 | */ 21 | public static void start() { 22 | QUERY_START.set(System.currentTimeMillis()); 23 | } 24 | 25 | /** 26 | * @param loggerTime 27 | * @param resultSize 28 | */ 29 | public static void stop(int loggerTime, int resultSize) { 30 | stop(loggerTime, resultSize, null); 31 | } 32 | 33 | /** 34 | * @param loggerTime 35 | * @param resultSize 36 | * @param sql 37 | */ 38 | public static void stop(int loggerTime, int resultSize, String sql) { 39 | if (!LOG.isInfoEnabled() || loggerTime <= 0) { 40 | return; 41 | } 42 | 43 | Long start = QUERY_START.get(); 44 | if (start == null) { 45 | start = 0L; 46 | } 47 | QUERY_START.remove(); 48 | 49 | int time = start == 0 ? loggerTime : (int) (System.currentTimeMillis() - start); 50 | if (time <= loggerTime && resultSize <= 10000) { 51 | return; 52 | } 53 | 54 | StringBuilder logs = new StringBuilder() 55 | .append("\n** SQL Slower/Many ***********************************************************************") 56 | .append("\nSQL: ").append(sql == null ? "Unknow" : sql); 57 | if (time > loggerTime) { 58 | logs.append("\nTime: ").append(time).append("ms"); 59 | } 60 | if (resultSize > 10000) { 61 | logs.append("\nResult(s): ").append(resultSize); 62 | } 63 | LOG.warn(logs); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/CompileException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | 5 | /** 6 | * 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, Feb 4, 2009 10 | * @version $Id: CompileException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public class CompileException extends PersistException { 13 | private static final long serialVersionUID = -1344641792787972588L; 14 | 15 | public CompileException(String message) { 16 | super(message); 17 | } 18 | 19 | public CompileException(String message, Throwable ex) { 20 | super(message, ex); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/JoinField.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.Field; 4 | import cn.devezhao.persist4j.dialect.Dialect; 5 | import cn.devezhao.persist4j.query.compiler.JoinTree.JoinNode; 6 | 7 | import java.util.Objects; 8 | 9 | /** 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, 10/11/08 13 | * @version $Id: JoinField.java 120 2016-01-07 11:49:05Z zhaofang123@gmail.com $ 14 | */ 15 | public class JoinField implements SelectItem { 16 | private static final long serialVersionUID = 6578159656188301525L; 17 | 18 | private final JoinNode tableNode; 19 | private final Field field; 20 | private final String fieldPath; 21 | private final SelectItemType type; 22 | 23 | private String name; 24 | private String alias; 25 | private Integer index; 26 | 27 | private String fullPath = null; 28 | 29 | private String aggregator; 30 | private String aggregatorSibling; 31 | private String aggregatorMode; 32 | 33 | JoinField(JoinNode tableNode, Field field, String fieldPath, SelectItemType type) { 34 | this.tableNode = tableNode; 35 | this.field = field; 36 | this.fieldPath = fieldPath; 37 | this.type = type; 38 | } 39 | 40 | JoinField(JoinField joinField, SelectItemType type) { 41 | this.tableNode = joinField.tableNode; 42 | this.field = joinField.field; 43 | this.fieldPath = joinField.fieldPath; 44 | this.type = type; 45 | } 46 | 47 | // --------------------------------------------------------------------- Implements SelectItem 48 | 49 | @Override 50 | public String getFieldPath() { 51 | return fieldPath; 52 | } 53 | 54 | @Override 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | @Override 60 | public String getAlias() { 61 | return alias; 62 | } 63 | 64 | @Override 65 | public int getIndex() { 66 | return index; 67 | } 68 | 69 | @Override 70 | public Field getField() { 71 | return field; 72 | } 73 | 74 | @Override 75 | public SelectItemType getType() { 76 | return type; 77 | } 78 | 79 | 80 | // --------------------------------------------------------------------- 81 | 82 | protected void setAggregator(String aggregator, String aggregatorSibling) { 83 | this.aggregator = aggregator; 84 | this.aggregatorSibling = aggregatorSibling; 85 | } 86 | 87 | public String getAggregator() { 88 | return aggregator; 89 | } 90 | 91 | public String getAggregatorSibling() { 92 | return aggregatorSibling; 93 | } 94 | 95 | protected void setAggregatorMode(String mode) { 96 | this.aggregatorMode = mode; 97 | } 98 | 99 | public String getAggregatorMode() { 100 | return aggregatorMode; 101 | } 102 | 103 | protected String as(int increase, Dialect dialect) { 104 | if (fullPath != null) { 105 | return fullPath; 106 | } 107 | 108 | index = increase; 109 | if (tableNode == null) { 110 | name = "$"; 111 | } else { 112 | name = String.format("%s.%s", 113 | tableNode.getAlias(), dialect.quote(field.getPhysicalName())); 114 | } 115 | alias = JoinTree.COLUMN_ALIAS_PREFIX + index; 116 | return (fullPath = name + " as " + alias); 117 | } 118 | 119 | @Override 120 | public String toString() { 121 | if (getAggregator() != null) { 122 | return String.format("%s%s[%s->%s->%s]", 123 | getAggregator(), (getAggregatorMode() == null ? "" : ("," + getAggregatorMode())), 124 | fieldPath, name, alias); 125 | } else { 126 | return String.format("[%s->%s->%s]", fieldPath, name, alias); 127 | } 128 | } 129 | 130 | @Override 131 | public boolean equals(Object o) { 132 | if (this == o) return true; 133 | if (o == null || getClass() != o.getClass()) return false; 134 | return o.hashCode() == hashCode(); 135 | } 136 | 137 | @Override 138 | public int hashCode() { 139 | return Objects.hash(tableNode, field, fieldPath, aggregator, aggregatorMode); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/NestedSelectContext.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.query.compiler.JoinTree.JoinNode; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @author zhaofang123@gmail.com 10 | * @since 10/27/2018 11 | */ 12 | public class NestedSelectContext implements Serializable { 13 | private static final long serialVersionUID = 7585161604688620934L; 14 | 15 | private Entity root; 16 | private JoinNode rootNode; 17 | private int tableIncrease; 18 | 19 | protected NestedSelectContext(Entity root, JoinNode rootNode, int tableIncrease) { 20 | this.root = root; 21 | this.rootNode = rootNode; 22 | this.tableIncrease = tableIncrease; 23 | } 24 | 25 | public Entity getRoot() { 26 | return root; 27 | } 28 | 29 | public JoinNode getRootNode() { 30 | return rootNode; 31 | } 32 | 33 | public int getTableIncrease() { 34 | return tableIncrease; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/ParameterItem.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.Field; 4 | 5 | import java.io.Serializable; 6 | import java.util.Objects; 7 | 8 | /** 9 | * @author FANGFANG ZHAO 10 | * @since 0.1, Apr 3, 2009 11 | * @version $Id: ParameterItem.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 12 | */ 13 | public class ParameterItem implements Serializable { 14 | private static final long serialVersionUID = 6919840306703366608L; 15 | 16 | private String named; 17 | private int index; 18 | private Field field; 19 | 20 | public ParameterItem(String named, int index, Field field) { 21 | this.named = named; 22 | this.index = index; 23 | this.field = field; 24 | } 25 | 26 | public String getNamed() { 27 | return named; 28 | } 29 | 30 | public int getIndex() { 31 | return index; 32 | } 33 | 34 | public Field getField() { 35 | return field; 36 | } 37 | 38 | @Override 39 | public boolean equals(Object o) { 40 | if (this == o) return true; 41 | if (o == null || getClass() != o.getClass()) return false; 42 | return hashCode() == o.hashCode(); 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | return Objects.hash(named, index); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/SelectItem.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.Field; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 9 | * 10 | * @author FANGFANG ZHAO 11 | * @since 0.1, Feb 15, 2009 12 | * @version $Id: SelectItem.java 120 2016-01-07 11:49:05Z zhaofang123@gmail.com $ 13 | */ 14 | public interface SelectItem extends Serializable { 15 | 16 | Field getField(); 17 | 18 | int getIndex(); 19 | 20 | String getName(); 21 | 22 | String getAlias(); 23 | 24 | String getFieldPath(); 25 | 26 | SelectItemType getType(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/SelectItemType.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | /** 4 | * @author FANGFANG ZHAO 5 | * @since 0.1, Feb 15, 2009 6 | * @version $Id: SelectItemType.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 7 | */ 8 | public enum SelectItemType { 9 | 10 | Aggregator, 11 | 12 | Field, 13 | 14 | NameField, 15 | 16 | IDLabelField 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/antlr/AjQLParserTokenTypes.java: -------------------------------------------------------------------------------- 1 | // $ANTLR 2.7.7 (2006-11-01): "ajql.g" -> "AjQLParser.java"$ 2 | 3 | package cn.devezhao.persist4j.query.compiler.antlr; 4 | 5 | public interface AjQLParserTokenTypes { 6 | int EOF = 1; 7 | int NULL_TREE_LOOKAHEAD = 3; 8 | int SELECT = 4; 9 | int DISTINCT = 5; 10 | int FROM = 6; 11 | int WHERE = 7; 12 | int AND = 8; 13 | int OR = 9; 14 | int ORDER = 10; 15 | int ASC = 11; 16 | int DESC = 12; 17 | int GROUP = 13; 18 | int BY = 14; 19 | int HAVING = 15; 20 | int WITH = 16; 21 | int ROLLUP = 17; 22 | int MAX = 18; 23 | int MIN = 19; 24 | int AVG = 20; 25 | int SUM = 21; 26 | int COUNT = 22; 27 | int DATE_FORMAT = 23; 28 | int YEAR = 24; 29 | int QUARTER = 25; 30 | int MONTH = 26; 31 | int WEEK = 27; 32 | int CONCAT = 28; 33 | int IS = 29; 34 | int NOT = 30; 35 | int NULL = 31; 36 | int IN = 32; 37 | int LIKE = 33; 38 | int EXISTS = 34; 39 | int BETWEEN = 35; 40 | int TRUE = 36; 41 | int FALSE = 37; 42 | int MATCH = 38; 43 | int GROUP_CONCAT = 39; 44 | int SEPARATOR = 40; 45 | int COMMA = 41; 46 | int LPAREN = 42; 47 | int QUOTED_STRING = 43; 48 | int RPAREN = 44; 49 | int IDENT = 45; 50 | int STAR = 46; 51 | int LITERAL = 47; 52 | int NAMED_PARAM = 48; 53 | int QUESTION_MARK = 49; 54 | int PLUS = 50; 55 | int MINUS = 51; 56 | int DIVIDE = 52; 57 | int MOD = 53; 58 | int EQ = 54; 59 | int LT = 55; 60 | int GT = 56; 61 | int LE = 57; 62 | int GE = 58; 63 | int SQL_NE = 59; 64 | int BAND = 60; 65 | int NBAND = 61; 66 | int DOT = 62; 67 | int COLON = 63; 68 | int IDENT_START = 64; 69 | int IDENT_LETTER = 65; 70 | int DIGIT = 66; 71 | int INT = 67; 72 | int NUM = 68; 73 | int ESCqs = 69; 74 | int WS = 70; 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/antlr/ParserException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler.antlr; 2 | 3 | import antlr.ANTLRException; 4 | import org.apache.commons.lang.exception.NestableRuntimeException; 5 | 6 | /** 7 | * @author FANGFANG ZHAO 8 | * @since 0.1, Feb 10, 2009 9 | * @version $Id: ParserException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 10 | */ 11 | public class ParserException extends NestableRuntimeException { 12 | private static final long serialVersionUID = -3556487161116352482L; 13 | 14 | public ParserException(String message) { 15 | super(message); 16 | } 17 | 18 | public ParserException(ANTLRException ex) { 19 | super(ex); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/antlr/ParserHelper.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler.antlr; 2 | 3 | import java.io.StringReader; 4 | 5 | /** 6 | * @author FANGFANG ZHAO 7 | * @since 0.1, Feb 4, 2009 8 | * @version $Id: ParserHelper.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 9 | */ 10 | public class ParserHelper { 11 | 12 | /** 13 | * @param ajql 14 | * @return 15 | */ 16 | public static AjQLParser createAjQLParser(String ajql) { 17 | return createAjQLParser(ajql, false); 18 | } 19 | 20 | /** 21 | * @param ajql 22 | * @param isThrow 23 | * @return 24 | */ 25 | public static AjQLParser createAjQLParser(String ajql, boolean isThrow) { 26 | AjQLLexer l = new AjQLLexer(new StringReader(ajql)); 27 | return (isThrow) ? new ThrowerAjQLParser(l) : new AjQLParser(l); 28 | } 29 | 30 | /** 31 | * @param type 32 | * @return 33 | * @see #isAggregatorWithMode(int) 34 | * @see #isAggregatorWithNested(int) 35 | */ 36 | public static boolean isAggregator(int type) { 37 | return type == AjQLParserTokenTypes.MIN 38 | || type == AjQLParserTokenTypes.MAX 39 | || type == AjQLParserTokenTypes.AVG 40 | || type == AjQLParserTokenTypes.SUM 41 | || type == AjQLParserTokenTypes.COUNT 42 | || type == AjQLParserTokenTypes.YEAR 43 | || type == AjQLParserTokenTypes.QUARTER 44 | || type == AjQLParserTokenTypes.MONTH 45 | || type == AjQLParserTokenTypes.WEEK 46 | || isAggregatorWithMode(type) 47 | || isAggregatorWithNested(type); 48 | } 49 | 50 | /** 51 | * @param type 52 | * @return 53 | */ 54 | public static boolean isAggregatorWithMode(int type) { 55 | return type == AjQLParserTokenTypes.DATE_FORMAT || type == AjQLParserTokenTypes.GROUP_CONCAT; 56 | } 57 | 58 | /** 59 | * @param type 60 | * @return 61 | */ 62 | public static boolean isAggregatorWithNested(int type) { 63 | return type == AjQLParserTokenTypes.CONCAT; 64 | } 65 | 66 | /** 67 | * 运算符 68 | * 69 | * @param type 70 | * @return 71 | */ 72 | public static boolean isOperator(int type) { 73 | return type == AjQLParserTokenTypes.EQ 74 | || type == AjQLParserTokenTypes.LT 75 | || type == AjQLParserTokenTypes.GT 76 | || type == AjQLParserTokenTypes.LE 77 | || type == AjQLParserTokenTypes.GE 78 | || type == AjQLParserTokenTypes.SQL_NE 79 | || type == AjQLParserTokenTypes.LIKE 80 | || type == AjQLParserTokenTypes.BETWEEN 81 | || type == AjQLParserTokenTypes.BAND 82 | || type == AjQLParserTokenTypes.NBAND 83 | || type == AjQLParserTokenTypes.MATCH; 84 | } 85 | 86 | /** 87 | * 逻辑符 88 | * 89 | * @param type 90 | * @return 91 | */ 92 | public static boolean isInIgnore(int type) { 93 | return type == AjQLParserTokenTypes.AND 94 | || type == AjQLParserTokenTypes.OR 95 | || type == AjQLParserTokenTypes.IS 96 | || type == AjQLParserTokenTypes.NOT 97 | || type == AjQLParserTokenTypes.LPAREN 98 | || type == AjQLParserTokenTypes.RPAREN 99 | || type == AjQLParserTokenTypes.COMMA 100 | || type == AjQLParserTokenTypes.MINUS 101 | || isOperator(type) 102 | || isInIgnoreValue(type); 103 | } 104 | 105 | /** 106 | * 特殊值 107 | * 108 | * @param type 109 | * @return 110 | */ 111 | public static boolean isInIgnoreValue(int type) { 112 | return type == AjQLParserTokenTypes.TRUE 113 | || type == AjQLParserTokenTypes.FALSE 114 | || type == AjQLParserTokenTypes.LITERAL 115 | || type == AjQLParserTokenTypes.NULL; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/query/compiler/antlr/ThrowerAjQLParser.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler.antlr; 2 | 3 | import antlr.RecognitionException; 4 | import antlr.TokenStream; 5 | 6 | /** 7 | * @author FANGFANG ZHAO 8 | * @since 0.1, Feb 10, 2009 9 | * @version $Id: ThrowerAjQLParser.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 10 | */ 11 | public class ThrowerAjQLParser extends AjQLParser { 12 | 13 | public ThrowerAjQLParser(TokenStream stream) { 14 | super(stream); 15 | } 16 | 17 | @Override 18 | public void reportError(RecognitionException ex) { 19 | throw new ParserException(ex); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/record/FieldValueException.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.record; 2 | 3 | import cn.devezhao.persist4j.PersistException; 4 | 5 | /** 6 | * Invald value of field 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 0.1, 06/14/08 10 | * @version $Id: FieldValueException.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 11 | */ 12 | public class FieldValueException extends PersistException { 13 | private static final long serialVersionUID = -2063367127310548765L; 14 | 15 | public FieldValueException(String message) { 16 | super(message); 17 | } 18 | 19 | public FieldValueException(String message, Throwable ex) { 20 | super(message, ex); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/record/JsonRecordCreator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 DEVEZHAO(zhaofang123@gmail.com) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cn.devezhao.persist4j.record; 18 | 19 | import cn.devezhao.persist4j.Entity; 20 | import cn.devezhao.persist4j.Field; 21 | import cn.devezhao.persist4j.Record; 22 | import cn.devezhao.persist4j.engine.ID; 23 | import cn.devezhao.persist4j.engine.StandardRecord; 24 | import com.alibaba.fastjson.JSONObject; 25 | import org.apache.commons.lang.Validate; 26 | import org.apache.commons.logging.Log; 27 | import org.apache.commons.logging.LogFactory; 28 | 29 | import java.util.Map; 30 | 31 | /** 32 | * JSON 记录解析 33 | * 34 | * @author zhaofang123@gmail.com 35 | * @since 08/01/2018 36 | */ 37 | public class JsonRecordCreator implements RecordCreator { 38 | 39 | private static final Log LOG = LogFactory.getLog(JsonRecordCreator.class); 40 | 41 | public static final String META_FIELD = "metadata"; 42 | 43 | final protected Entity entity; 44 | final protected ID editor; 45 | final protected JSONObject source; 46 | 47 | /** 48 | * Create a new JsonRecordCreator. the format of document like 49 | *
 50 | 	 * {
 51 | 	 *   metadata: { entity: 'User', [id='xx'] },
 52 | 	 *   loginName: 'xx',
 53 | 	 *   email: 'xx'
 54 | 	 * }
 55 | 	 * 
56 | * 57 | * @param entity 58 | * @param source 59 | */ 60 | public JsonRecordCreator(Entity entity, JSONObject source) { 61 | this(entity, source, null); 62 | } 63 | 64 | /** 65 | * 66 | * @param entity 67 | * @param source 68 | * @param editor 69 | */ 70 | public JsonRecordCreator(Entity entity, JSONObject source, ID editor) { 71 | Validate.notNull(entity); 72 | Validate.notNull(source); 73 | this.entity = entity; 74 | this.source = source; 75 | this.editor = editor; 76 | } 77 | 78 | /** 79 | * @return 80 | */ 81 | @Override 82 | public Record create() { 83 | return create(true); 84 | } 85 | 86 | /** 87 | * @param ignoreNullValueWhenNew 忽略空值(仅在新建时有效) 88 | * @return 89 | */ 90 | public Record create(boolean ignoreNullValueWhenNew) { 91 | Record record = new StandardRecord(entity, editor); 92 | 93 | JSONObject metadata = source.getJSONObject(META_FIELD); 94 | if (metadata == null) { 95 | throw new FieldValueException("The `metadata` element must not be null"); 96 | } 97 | 98 | String id = metadata.getString("id"); 99 | if (ID.isId(id)) { 100 | record.setID(entity.getPrimaryField().getName(), ID.valueOf(id)); 101 | } 102 | 103 | for (Map.Entry e : source.entrySet()) { 104 | String fileName = e.getKey(); 105 | if (META_FIELD.equals(fileName)) continue; 106 | 107 | final Field field = entity.containsField(fileName) ? entity.getField(fileName) : null; 108 | if (field == null) { 109 | LOG.warn("Unable found field [ " + entity.getName() + '#' + fileName + " ], will ignore"); 110 | continue; 111 | } 112 | 113 | Object fieldValue = e.getValue(); 114 | if (fieldValue != null) fieldValue = fieldValue.toString(); 115 | 116 | if (ignoreNullValueWhenNew && record.getPrimary() == null 117 | && (fieldValue == null || isNoValue((String) fieldValue, field))) { 118 | continue; 119 | } 120 | 121 | setFieldValue(field, (String) fieldValue, record); 122 | } 123 | 124 | afterCreate(record); 125 | return record; 126 | } 127 | 128 | protected void afterCreate(Record record) { 129 | verify(record); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/record/RecordCreator.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.record; 2 | 3 | import cn.devezhao.persist4j.Field; 4 | import cn.devezhao.persist4j.Record; 5 | import cn.devezhao.persist4j.dialect.FieldType; 6 | import cn.devezhao.persist4j.engine.NullValue; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.apache.commons.logging.Log; 9 | import org.apache.commons.logging.LogFactory; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author FANGFANG ZHAO 16 | * @version $Id: RecordCreator.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 17 | * @since 0.1, Feb 14, 2009 18 | */ 19 | public interface RecordCreator { 20 | 21 | Log LOG = LogFactory.getLog(RecordCreator.class); 22 | 23 | /** 24 | * 创建 Record 25 | * 26 | * @return 27 | */ 28 | Record create(); 29 | 30 | /** 31 | * #setFieldValue 产生警告时调用 32 | * 33 | * @param field 34 | * @param value 35 | * @param record 36 | * @return 37 | */ 38 | default boolean onSetFieldValueWarn(Field field, String value, Record record) { 39 | return false; 40 | } 41 | 42 | /** 43 | * 设置字段值 44 | * 45 | * @param field 46 | * @param value 47 | * @param record 48 | * @return 49 | */ 50 | default boolean setFieldValue(Field field, String value, Record record) { 51 | final boolean isNew = record.getPrimary() == null; 52 | 53 | // 忽略更新 54 | if (!isNew && !field.isUpdatable()) { 55 | if (!onSetFieldValueWarn(field, value, record)) { 56 | LOG.warn("Could not put value to un-updatable field : " + field); 57 | return false; 58 | } 59 | } 60 | 61 | // 忽略新建 62 | if (isNew && !field.isCreatable()) { 63 | if (!onSetFieldValueWarn(field, value, record)) { 64 | LOG.warn("Could not put value to un-creatable field : " + field); 65 | return false; 66 | } 67 | } 68 | 69 | final boolean noValue = isNoValue(value, field); 70 | 71 | // 无值 72 | if (noValue) { 73 | if (isNew && !field.isNullable() && !field.isAutoValue()) { 74 | throw new FieldValueException("Field [ " + field + " ] must not be null"); 75 | } 76 | } 77 | 78 | if (noValue) { 79 | record.setNull(field.getName()); 80 | } else { 81 | try { 82 | RecordVisitor.setValueByLiteral(field, value, record); 83 | } catch (Exception ex) { 84 | LOG.error("Invalid field value by literal : " + field.getName() + " = " + value); 85 | throw ex; 86 | } 87 | } 88 | return true; 89 | } 90 | 91 | /** 92 | * 验证字段约束 93 | * 94 | * @param record 95 | */ 96 | default void verify(Record record) { 97 | if (record.getPrimary() == null) return; 98 | 99 | List notNullable = new ArrayList<>(); 100 | for (Field field : record.getEntity().getFields()) { 101 | if (FieldType.PRIMARY.equals(field.getType())) continue; 102 | 103 | Object val = record.getObjectValue(field.getName()); 104 | if (!field.isNullable() && !field.isAutoValue() && (val == null || NullValue.is(val))) { 105 | notNullable.add(field.getName()); 106 | } 107 | } 108 | 109 | if (!notNullable.isEmpty()) { 110 | throw new FieldValueException("Must not be null. Entity [ " + record.getEntity().getName() 111 | + " ], Fields [ " + StringUtils.join(notNullable.toArray(new String[0]), ", ") + " ]"); 112 | } 113 | } 114 | 115 | /** 116 | * 是否无值/空值 117 | * 118 | * @param value 119 | * @param field 120 | * @return 121 | */ 122 | default boolean isNoValue(String value, Field field) { 123 | return value == null || StringUtils.isEmpty(value); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/record/XmlBean.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.record; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.engine.ID; 5 | 6 | /** 7 | * 8 | * 9 | * @author FANGFANG ZHAO 10 | * @since 0.1, Feb 14, 2009 11 | * @version $Id: XMLBean.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 12 | */ 13 | public class XmlBean { 14 | 15 | public XmlBean(Entity entity) { 16 | } 17 | 18 | public XmlBean(Entity entity, ID recordId) { 19 | } 20 | 21 | public XmlBean addValue(String fieldName, String value) { 22 | return this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/record/XmlRecordCreator.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.record; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.Field; 5 | import cn.devezhao.persist4j.Record; 6 | import cn.devezhao.persist4j.engine.ID; 7 | import cn.devezhao.persist4j.engine.StandardRecord; 8 | import org.apache.commons.lang.StringUtils; 9 | import org.apache.commons.lang.Validate; 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | import org.dom4j.Element; 13 | 14 | /** 15 | * @author FANGFANG ZHAO 16 | * @since 0.1, Feb 14, 2009 17 | * @version $Id: XMLRecordCreator.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 18 | */ 19 | @Deprecated 20 | public class XmlRecordCreator implements RecordCreator { 21 | 22 | private static final Log LOG = LogFactory.getLog(XmlRecordCreator.class); 23 | 24 | final protected Entity entity; 25 | final protected ID editor; 26 | final protected Element source; 27 | 28 | /** 29 | * Create a new XmlRecordCreator. the format of document like 30 | *
31 | 	 * <entity name="..." [id="..."]>
32 | 	 *    <userName value="..." [label"..."]/>
33 | 	 *    <description>
34 | 	 *       ...
35 | 	 *    </description>
36 | 	 * </entity>
37 | 	 * 
38 | * 39 | * @param entity 40 | * @param source 41 | */ 42 | public XmlRecordCreator(Entity entity, Element source) { 43 | this(entity, source, null); 44 | } 45 | 46 | /** 47 | * 48 | * @param entity 49 | * @param source 50 | * @param editor 51 | */ 52 | public XmlRecordCreator(Entity entity, Element source, ID editor) { 53 | Validate.notNull(entity); 54 | Validate.notNull(source); 55 | this.entity = entity; 56 | this.source = source; 57 | this.editor = editor; 58 | } 59 | 60 | @Override 61 | public Record create() { 62 | Record record = new StandardRecord(entity, editor); 63 | 64 | String id = source.valueOf("@id"); 65 | if (!StringUtils.isBlank(id)) { 66 | record.setID(entity.getPrimaryField().getName(), ID.valueOf(id)); 67 | } 68 | 69 | for (Object o : source.elements()) { 70 | Element el = (Element) o; 71 | String fieldName = el.getName(); 72 | String fieldValue = el.attributeValue("value"); 73 | if (fieldValue == null) { 74 | fieldValue = el.getText(); 75 | } 76 | 77 | Field field = entity.containsField(fieldName) ? entity.getField(fieldName) : null; 78 | if (field == null) { 79 | LOG.warn("Unable found field [ " + entity.getName() + '#' + fieldName + " ], will ignore"); 80 | continue; 81 | } 82 | 83 | setFieldValue(field, fieldValue, record); 84 | } 85 | 86 | afterCreate(record); 87 | return record; 88 | } 89 | 90 | protected void afterCreate(Record record) { 91 | verify(record); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/util/CaseInsensitiveMap.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 大小写不敏感 Map 7 | * 8 | * @author FANGFANG ZHAO 9 | * @since 08/17/2019 10 | */ 11 | public class CaseInsensitiveMap implements Map { 12 | 13 | private Map originalKeys = new HashMap<>(); 14 | 15 | private Map delegate = new org.apache.commons.collections4.map.CaseInsensitiveMap<>(); 16 | 17 | public CaseInsensitiveMap() { 18 | super(); 19 | } 20 | 21 | public CaseInsensitiveMap(Map m) { 22 | this(); 23 | this.putAll(m); 24 | } 25 | 26 | @Override 27 | public int size() { 28 | return delegate.size(); 29 | } 30 | 31 | @Override 32 | public boolean isEmpty() { 33 | return delegate.isEmpty(); 34 | } 35 | 36 | @Override 37 | public boolean containsKey(Object key) { 38 | return delegate.containsKey(key); 39 | } 40 | 41 | @Override 42 | public boolean containsValue(Object value) { 43 | return delegate.containsValue(value); 44 | } 45 | 46 | @Override 47 | public V get(Object key) { 48 | return delegate.get(key); 49 | } 50 | 51 | @Override 52 | public V put(String key, V value) { 53 | originalKeys.put(convertKey(key), key); 54 | return delegate.put(key, value); 55 | } 56 | 57 | @Override 58 | public V remove(Object key) { 59 | originalKeys.remove(convertKey(key)); 60 | return delegate.remove(key); 61 | } 62 | 63 | @Override 64 | public void putAll(Map m) { 65 | for (String key : m.keySet()) { 66 | originalKeys.put(convertKey(key), key); 67 | } 68 | delegate.putAll(m); 69 | } 70 | 71 | @Override 72 | public void clear() { 73 | originalKeys.clear(); 74 | delegate.clear(); 75 | } 76 | 77 | @Override 78 | public Set keySet() { 79 | return new HashSet<>(originalKeys.values()); 80 | } 81 | 82 | @Override 83 | public Collection values() { 84 | return delegate.values(); 85 | } 86 | 87 | @Override 88 | public Set> entrySet() { 89 | Set> es = new HashSet<>(); 90 | for (Entry e : delegate.entrySet()) { 91 | String oKey = originalKeys.get(convertKey(e.getKey())); 92 | es.add(new CIEntry(oKey, e.getValue())); 93 | } 94 | return es; 95 | } 96 | 97 | private String convertKey(final Object key) { 98 | return key.toString().toUpperCase(); 99 | } 100 | 101 | /** 102 | */ 103 | class CIEntry implements Entry { 104 | 105 | private String key; 106 | private V value; 107 | 108 | protected CIEntry(String key, V value) { 109 | this.key = key; 110 | this.value = value; 111 | } 112 | 113 | @Override 114 | public String getKey() { 115 | return key; 116 | } 117 | @Override 118 | public V getValue() { 119 | return value; 120 | } 121 | @Override 122 | public V setValue(V value) { 123 | this.value = value; 124 | return value; 125 | } 126 | @Override 127 | public String toString() { 128 | return String.format("%s=%s", key, value); 129 | } 130 | 131 | @Override 132 | public boolean equals(Object o) { 133 | if (this == o) return true; 134 | if (o == null || getClass() != o.getClass()) return false; 135 | return o.hashCode() == hashCode(); 136 | } 137 | 138 | @Override 139 | public int hashCode() { 140 | return Objects.hash(key, value); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/util/StringHelper.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util; 2 | 3 | import org.apache.commons.lang.CharSet; 4 | import org.apache.commons.lang.StringUtils; 5 | 6 | /** 7 | * @author FANGFANG ZHAO 8 | * @version $Id: StringHelper.java 119 2011-05-15 16:56:18Z 9 | * zhaofang123@gmail.com $ 10 | * @since 0.1, Feb 17, 2009 11 | */ 12 | public class StringHelper { 13 | 14 | private StringHelper() { 15 | } 16 | 17 | /** 18 | * 验证字符有效 19 | * 规则:['a-zA-Z', '_', '#'], can contains ['a-zA-Z', '_', '#', '0-9'] 20 | * 21 | * @param ident 22 | * @return 23 | */ 24 | public static boolean isIdentifier(String ident) { 25 | if (StringUtils.isBlank(ident)) { 26 | return false; 27 | } 28 | 29 | char start = ident.charAt(0); 30 | if (!(CharSet.ASCII_ALPHA.contains(start) || start == '_' || start == '#')) { 31 | return false; 32 | } 33 | 34 | for (char ch : ident.toCharArray()) { 35 | if (!(CharSet.ASCII_ALPHA.contains(ch) || CharSet.ASCII_NUMERIC.contains(ch) || ch == '_' || ch == '#')) { 36 | return false; 37 | } 38 | } 39 | 40 | return true; 41 | } 42 | 43 | /** 44 | * 根据驼峰加入下划线并大些,例如:userName > USER_NAME 45 | * 46 | * @param s 47 | * @return 48 | */ 49 | public static String hyphenate(final String s) { 50 | char[] chars = s.toCharArray(); 51 | int lenth = s.length(); 52 | 53 | StringBuilder sb = new StringBuilder(); 54 | boolean lastAZ = false; 55 | boolean lastInsert = false; 56 | for (int i = 0; i < lenth; i++) { 57 | char ch = chars[i]; 58 | if (ch >= 'A' && ch <= 'Z') { 59 | if (i > 0) { 60 | if (!lastAZ) { 61 | sb.append('_'); 62 | lastInsert = true; 63 | } else { 64 | lastInsert = false; 65 | } 66 | } 67 | 68 | lastAZ = true; 69 | } else { 70 | if (lastAZ) { 71 | if (!lastInsert && i > 1) { 72 | if (!(ch >= '0' && ch <= '9')) { 73 | sb.insert(sb.length() - 1, '_'); 74 | } 75 | } 76 | } 77 | 78 | lastAZ = false; 79 | lastInsert = false; 80 | } 81 | sb.append(ch); 82 | } 83 | return sb.toString().replaceAll("__", "_").toLowerCase(); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/util/support/QueryHelper.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util.support; 2 | 3 | import cn.devezhao.persist4j.Query; 4 | import cn.devezhao.persist4j.Record; 5 | import cn.devezhao.persist4j.query.IQuery; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * @author Zhao Fangfang 13 | * @version $Id: QueryHelper.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 14 | * @since 2.6, 2012-10-22 15 | */ 16 | public class QueryHelper { 17 | 18 | /** 19 | * 分页读取 20 | * 21 | * @param query 22 | * @return 23 | */ 24 | public static Object[][] readArray(IQuery query) { 25 | return readArray(query, 10000); 26 | } 27 | 28 | /** 29 | * 分页读取 30 | * 31 | * @param query 32 | * @param pageSize 33 | * @return 34 | */ 35 | public static Object[][] readArray(IQuery query, int pageSize) { 36 | List tempList = new ArrayList<>(); 37 | int pageNo = 1; 38 | while (true) { 39 | query.reset(); 40 | query.setLimit(pageSize, pageNo++ * pageSize - pageSize); 41 | Object[][] temp = query.array(); 42 | Collections.addAll(tempList, temp); 43 | 44 | if (temp.length < pageSize) { 45 | break; 46 | } 47 | } 48 | return tempList.toArray(new Object[tempList.size()][]); 49 | } 50 | 51 | /** 52 | * 分页读取 53 | * 54 | * @param query 55 | * @return 56 | */ 57 | public static List readList(Query query) { 58 | return readList(query, 10000); 59 | } 60 | 61 | /** 62 | * 分页读取 63 | * 64 | * @param query 65 | * @param pageSize 66 | * @return 67 | */ 68 | public static List readList(Query query, int pageSize) { 69 | List tempList = new ArrayList<>(); 70 | int pageNo = 1; 71 | while (true) { 72 | query.result().reset(); 73 | query.setLimit(pageSize, pageNo++ * pageSize - pageSize); 74 | List temp = query.list(); 75 | tempList.addAll(temp); 76 | 77 | if (temp.size() < pageSize) { 78 | break; 79 | } 80 | } 81 | return tempList; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/util/support/SchemaExport.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util.support; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.PersistException; 5 | import cn.devezhao.persist4j.dialect.Dialect; 6 | import cn.devezhao.persist4j.metadata.MetadataFactory; 7 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 8 | import cn.devezhao.persist4j.util.SqlHelper; 9 | import org.dom4j.Element; 10 | 11 | import java.sql.Connection; 12 | import java.sql.SQLException; 13 | import java.sql.Statement; 14 | import java.util.List; 15 | 16 | /** 17 | * 生成建表语句 18 | * 19 | * @author FANGFANG ZHAO 20 | * @since 0.1, 06/15/08 21 | * @version $Id: SchemaExport.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 22 | */ 23 | public class SchemaExport { 24 | 25 | final private MetadataFactory metadataFactory; 26 | final private Dialect dialect; 27 | final private Connection connection; 28 | 29 | /** 30 | * @param metadataFactory 31 | * @param dialect 32 | * @param connect 33 | */ 34 | public SchemaExport(MetadataFactory metadataFactory, Dialect dialect, Connection connect) { 35 | this.metadataFactory = metadataFactory; 36 | this.dialect = dialect; 37 | this.connection = connect; 38 | } 39 | 40 | /** 41 | * @param dropExists 42 | * @param createFK 43 | */ 44 | @SuppressWarnings("deprecation") 45 | public void export(boolean dropExists, boolean createFK) { 46 | Entity[] entities = metadataFactory.getEntities(); 47 | Element cfgRoot = ((ConfigurationMetadataFactory) metadataFactory).getConfigDocument().getRootElement(); 48 | 49 | try { 50 | for (Entity entity : entities) { 51 | Element entityElement = (Element) cfgRoot.selectSingleNode("//entity[@name='" + entity.getName() + "']"); 52 | List ix = entityElement.selectNodes("index"); 53 | String[] sqls = new Table(entity, dialect, ix).generateDDL(dropExists, createFK); 54 | 55 | for (String sql : sqls) { 56 | try (Statement stmt = connection.createStatement()) { 57 | stmt.execute(sql); 58 | } 59 | } 60 | } 61 | } catch (SQLException e) { 62 | throw new PersistException(null, e); 63 | } finally { 64 | SqlHelper.close(connection); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/cn/devezhao/persist4j/util/support/SecurityPreferencesConfigurer.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util.support; 2 | 3 | import org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer; 4 | 5 | import java.io.IOException; 6 | import java.util.Properties; 7 | 8 | /** 9 | * 10 | * 11 | * @author FANGFANG ZHAO 12 | * @since 0.1, 12/04/08 13 | * @version $Id: SecurityPreferencesConfigurer.java 8 2015-06-08 09:09:03Z zhaofang123@gmail.com $ 14 | */ 15 | public class SecurityPreferencesConfigurer extends PreferencesPlaceholderConfigurer { 16 | 17 | @Override 18 | protected void loadProperties(Properties props) throws IOException { 19 | super.loadProperties(props); 20 | this.afterLoad(props); 21 | } 22 | 23 | /*- 24 | */ 25 | protected void afterLoad(Properties props) { 26 | String dbUrl = props.getProperty("db.url"); 27 | 28 | if (dbUrl.startsWith("jdbc:mysql://")) { 29 | String append = ""; 30 | // Fix MySQL Connector/J 3.1 or higher Bugs 31 | if (!dbUrl.contains("zeroDateTimeBehavior")) { 32 | append = "&zeroDateTimeBehavior=convertToNull"; 33 | } 34 | 35 | // MySQL using PreparedStatement. MUST BE MYSQL5 OR HIGHER 36 | if (!dbUrl.contains("useServerPrepStmts")) { 37 | append += "&useServerPrepStmts=true"; 38 | } 39 | 40 | if (append.length() > 1) { 41 | props.put("db.url", dbUrl + append); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/metadata.dtd: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 15 | 19 | 20 | 23 | 24 | 40 | 55 | 56 | 59 | 60 | 79 | 98 | 99 | 102 | 103 | 108 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/BaseTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.dialect.Dialect; 4 | import cn.devezhao.persist4j.dialect.h2.H2Dialect; 5 | import cn.devezhao.persist4j.engine.PersistManagerFactoryImpl; 6 | import cn.devezhao.persist4j.metadata.MetadataFactory; 7 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 8 | import cn.devezhao.persist4j.util.support.SchemaExport; 9 | import com.alibaba.druid.pool.DruidDataSourceFactory; 10 | 11 | import javax.sql.DataSource; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author zhaofang123@gmail.com 17 | * @since 11/27/2019 18 | */ 19 | public class BaseTest { 20 | 21 | private DataSource ds; 22 | private PersistManagerFactory persistManagerFactory; 23 | 24 | /** 25 | * 获取持久化工厂 26 | * 27 | * @return 28 | */ 29 | protected PersistManagerFactory getPersistManagerFactory() { 30 | if (persistManagerFactory == null) { 31 | Dialect dialect = new H2Dialect(); 32 | MetadataFactory metadata = new ConfigurationMetadataFactory("metadata-test.xml", dialect); 33 | this.persistManagerFactory = new PersistManagerFactoryImpl(getDataSource(), dialect, metadata); 34 | } 35 | return persistManagerFactory; 36 | } 37 | 38 | /** 39 | * 获取 H2 数据源(内存表)。已知于 MySQL 兼容问题: 40 | * 1. 不支持 double(不支持指定小数位) 41 | * 2. 不支付全文索引,及对 CLOB/TEXT 字段建立索引 42 | * 43 | * @return 44 | */ 45 | protected DataSource getDataSource() { 46 | if (ds == null) { 47 | Map dbProps = new HashMap<>(); 48 | dbProps.put("url", "jdbc:h2:mem:test;MODE=MYSQL;DATABASE_TO_LOWER=TRUE;IGNORECASE=TRUE"); 49 | dbProps.put("testWhileIdle", "false"); 50 | try { 51 | this.ds = DruidDataSourceFactory.createDataSource(dbProps); 52 | } catch (Exception e) { 53 | throw new RuntimeException(e); 54 | } 55 | } 56 | return ds; 57 | } 58 | 59 | /** 60 | * 建表 61 | * 62 | * @throws Exception 63 | */ 64 | protected void readySchemes() throws Exception { 65 | PersistManagerFactory factory = getPersistManagerFactory(); 66 | SchemaExport schemaExport = new SchemaExport( 67 | factory.getMetadataFactory(), factory.getDialect(), factory.getDataSource().getConnection()); 68 | schemaExport.export(false, false); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/RecordTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j; 2 | 3 | import cn.devezhao.persist4j.dialect.Dialect; 4 | import cn.devezhao.persist4j.dialect.MySQL5Dialect; 5 | import cn.devezhao.persist4j.engine.ID; 6 | import cn.devezhao.persist4j.engine.StandardRecord; 7 | import cn.devezhao.persist4j.metadata.MetadataFactory; 8 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 9 | import org.junit.Test; 10 | 11 | import java.math.BigDecimal; 12 | import java.util.Iterator; 13 | 14 | /** 15 | * 16 | * @author zhaofang123@gmail.com 17 | * @since 12/28/2018 18 | */ 19 | public class RecordTest { 20 | 21 | @Test 22 | public void testAnyReference() throws Exception { 23 | Dialect dialect = new MySQL5Dialect(); 24 | MetadataFactory metadataFactory = new ConfigurationMetadataFactory("metadata-test.xml", dialect); 25 | Entity allTypes = metadataFactory.getEntity(100); 26 | 27 | Record record = new StandardRecord(allTypes); 28 | record.setID("tAnyReference2", ID.newId(102)); 29 | record.setID("tAnyReference2", ID.newId(103)); 30 | 31 | for (Iterator iter = record.getAvailableFieldIterator(); iter.hasNext(); ) { 32 | System.out.println(iter.next()); 33 | } 34 | } 35 | 36 | @Test 37 | public void testTypeCompatible() throws Exception { 38 | Dialect dialect = new MySQL5Dialect(); 39 | MetadataFactory metadataFactory = new ConfigurationMetadataFactory("metadata-test.xml", dialect); 40 | Entity allTypes = metadataFactory.getEntity(100); 41 | 42 | Record record = new StandardRecord(allTypes); 43 | 44 | record.setInt("tLong", 123); 45 | System.out.println(record.getInt("tLong")); 46 | record.setLong("tInt", 123L); 47 | System.out.println(record.getLong("tInt")); 48 | 49 | record.setDecimal("tDouble", BigDecimal.valueOf(123.123d)); 50 | System.out.println(record.getDouble("tDouble")); 51 | record.setDouble("tDecimal", 123.123D); 52 | System.out.println(record.getDecimal("tDecimal")); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/engine/PersistManagerTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.engine; 2 | 3 | import cn.devezhao.commons.CalendarUtils; 4 | import cn.devezhao.persist4j.BaseTest; 5 | import cn.devezhao.persist4j.PersistManagerFactory; 6 | import cn.devezhao.persist4j.Record; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.junit.Test; 9 | 10 | import java.time.LocalTime; 11 | 12 | /** 13 | * @author devezhao zhaofang123@gmail.com 14 | * @since 2019年11月28日 15 | */ 16 | public class PersistManagerTest extends BaseTest { 17 | 18 | @Test 19 | public void testComplicated() throws Exception { 20 | this.readySchemes(); 21 | PersistManagerFactory factory = getPersistManagerFactory(); 22 | 23 | Record record = new StandardRecord(factory.getMetadataFactory().getEntity("TestAllType")); 24 | record.setString("tText", "CLOB/Text"); 25 | record.setIDArray("tReferenceList", new ID[] { ID.newId(100), ID.newId(100) }); 26 | record.setObjectValue("tTime", LocalTime.now()); 27 | record.setDate("tTime", CalendarUtils.now()); 28 | factory.createPersistManager().save(record); 29 | 30 | Object[][] array = factory.createQuery("select tText,tReferenceList,tTime from TestAllType").setLimit(1).array(); 31 | for (Object[] o : array) { 32 | System.out.println(o[0]); 33 | System.out.println(StringUtils.join((ID[]) o[1], ",")); 34 | System.out.println(o[2]); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/metadata/MetadataTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.metadata; 2 | 3 | import cn.devezhao.persist4j.Entity; 4 | import cn.devezhao.persist4j.Field; 5 | import cn.devezhao.persist4j.dialect.Dialect; 6 | import cn.devezhao.persist4j.dialect.MySQL5Dialect; 7 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 8 | import org.apache.commons.lang.StringUtils; 9 | import org.junit.Test; 10 | 11 | import java.util.Arrays; 12 | 13 | /** 14 | * @author zhaofang123@gmail.com 15 | * @since 12/28/2018 16 | */ 17 | public class MetadataTest { 18 | 19 | @Test 20 | public void testAnyReference() throws Exception { 21 | final MetadataFactory metadataFactory = createMetadataFactory(); 22 | 23 | Entity allTypes = metadataFactory.getEntity(100); 24 | Field anyReference1 = allTypes.getField("tanyreference"); 25 | System.out.println(anyReference1.getType() + " : " + StringUtils.join(anyReference1.getReferenceEntities(), " | ")); 26 | 27 | Field anyReference2 = allTypes.getField("tanyreference2"); 28 | System.out.println(anyReference2.getType() + " : " + StringUtils.join(anyReference2.getReferenceEntities(), " | ")); 29 | } 30 | 31 | @Test 32 | public void testReferenceToFields() throws Exception { 33 | final MetadataFactory metadataFactory = createMetadataFactory(); 34 | 35 | Entity test = metadataFactory.getEntity(102); 36 | for (Field field : test.getReferenceToFields()) { 37 | System.out.println(field); 38 | } 39 | } 40 | 41 | @Test 42 | public void testCommon() { 43 | final MetadataFactory metadataFactory = createMetadataFactory(); 44 | 45 | Field commonReference = metadataFactory.getEntity("Test2").getField("commonReference"); 46 | System.out.println(commonReference); 47 | } 48 | 49 | @Test 50 | public void testNDetails() { 51 | final MetadataFactory metadataFactory = createMetadataFactory(); 52 | 53 | Entity main = metadataFactory.getEntity(200); 54 | System.out.println(main.getDetailEntity()); 55 | System.out.println(Arrays.toString(main.getDetialEntities())); 56 | 57 | Entity detail1 = metadataFactory.getEntity(201); 58 | System.out.println(detail1.getMainEntity()); 59 | 60 | Entity detail2 = metadataFactory.getEntity(202); 61 | System.out.println(detail2.getMainEntity()); 62 | 63 | System.out.println(detail1.getMainEntity() == (detail2.getMainEntity())); 64 | } 65 | 66 | static MetadataFactory createMetadataFactory() { 67 | Dialect dialect = new MySQL5Dialect(); 68 | return new ConfigurationMetadataFactory("metadata-test.xml", dialect); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/query/QueryTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query; 2 | 3 | import cn.devezhao.persist4j.BaseTest; 4 | import cn.devezhao.persist4j.Query; 5 | import cn.devezhao.persist4j.engine.ID; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author FANGFANG ZHAO 10 | * @since 04/16/2020 11 | */ 12 | public class QueryTest extends BaseTest { 13 | 14 | @Test 15 | public void testParameterInNested() throws Exception { 16 | readySchemes(); 17 | createQuery("select tPrimary from TestAllType where tDouble > ? and" 18 | + " tInt in (select tInt from TestAllType where tPrimary = ?)") 19 | .setParameter(1, 1d) 20 | .setParameter(2, ID.newId(0)) 21 | .unique(); 22 | } 23 | 24 | @Test 25 | public void testParameterExistsNested() throws Exception { 26 | readySchemes(); 27 | createQuery("select tPrimary from TestAllType where" 28 | + " exists (select t2Primary from Test2 where ^tReference = t2Reference and t2Int = ?) and" 29 | + " tText = ?") 30 | .setParameter(1, 1) 31 | .setParameter(2, "123") 32 | .unique(); 33 | } 34 | 35 | @Test 36 | public void testParameterInAndExistsNested() throws Exception { 37 | readySchemes(); 38 | createQuery("select tPrimary from TestAllType where" 39 | + " exists (select t2Primary from Test2 where ^tReference = t2Reference and t2Int = ?) and" 40 | + " tText = ? and" 41 | + " tInt in (select tInt from TestAllType where tPrimary = ?)") 42 | .setParameter(1, 1) 43 | .setParameter(2, "123") 44 | .setParameter(3, ID.newId(0)) 45 | .unique(); 46 | } 47 | 48 | /** 49 | * 创建查询 50 | * 51 | * @param ajql 52 | * @return 53 | */ 54 | private Query createQuery(String ajql) { 55 | return getPersistManagerFactory().createQuery(ajql); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/query/compiler/Compiler.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.query.compiler; 2 | 3 | import cn.devezhao.persist4j.PersistManagerFactory; 4 | import cn.devezhao.persist4j.dialect.Dialect; 5 | import cn.devezhao.persist4j.dialect.MySQL5Dialect; 6 | import cn.devezhao.persist4j.engine.PersistManagerFactoryImpl; 7 | import cn.devezhao.persist4j.metadata.MetadataFactory; 8 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 9 | 10 | /** 11 | * 12 | * @author zhaofang123@gmail.com 13 | * @since 03/05/2018 14 | */ 15 | public class Compiler { 16 | 17 | /** 18 | * @param ajql 19 | * @return 20 | */ 21 | protected String compile(String ajql) { 22 | Dialect dialect = new MySQL5Dialect(); 23 | MetadataFactory metadataFactory = new ConfigurationMetadataFactory("metadata-test.xml", dialect); 24 | PersistManagerFactory persistManagerFactory = new PersistManagerFactoryImpl(null, dialect, metadataFactory); 25 | QueryCompiler queryCompiler = new QueryCompiler(ajql); 26 | String rawSql = queryCompiler.compile(persistManagerFactory.getSQLExecutorContext()); 27 | queryCompiler.getSelectItems(); 28 | return rawSql; 29 | } 30 | 31 | /** 32 | * @param ajql 33 | * @return 34 | */ 35 | protected QueryCompiler createCompiler(String ajql) { 36 | Dialect dialect = new MySQL5Dialect(); 37 | MetadataFactory metadataFactory = new ConfigurationMetadataFactory("metadata-test.xml", dialect); 38 | PersistManagerFactory persistManagerFactory = new PersistManagerFactoryImpl(null, dialect, metadataFactory); 39 | QueryCompiler queryCompiler = new QueryCompiler(ajql); 40 | queryCompiler.compile(persistManagerFactory.getSQLExecutorContext()); 41 | return queryCompiler; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/record/RecordVisitorTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.record; 2 | 3 | import org.junit.Test; 4 | 5 | public class RecordVisitorTest { 6 | 7 | @Test 8 | public void testClearNumber() { 9 | System.out.println(RecordVisitor.clearNumber("123 ", Boolean.TRUE)); 10 | System.out.println(RecordVisitor.clearNumber("123d ", Boolean.TRUE)); 11 | System.out.println(RecordVisitor.clearNumber("1,123 ", Boolean.TRUE)); 12 | System.out.println(RecordVisitor.clearNumber("111,1,11,,123.00 ", Boolean.FALSE)); 13 | System.out.println(RecordVisitor.clearNumber("NaN", Boolean.TRUE)); 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/util/CaseInsensitiveMapTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Map; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.assertFalse; 9 | 10 | /** 11 | * @author zhaofang123@gmail.com 12 | * @since 12/21/2018 13 | */ 14 | public class CaseInsensitiveMapTest { 15 | 16 | @Test 17 | public void testMap() throws Exception { 18 | Map map = new CaseInsensitiveMap<>(); 19 | 20 | map.put("abc", "1"); 21 | map.put("Abc", "11"); 22 | map.put("AbC", "111"); 23 | map.put("abcd", "2"); 24 | map.remove("ABCd"); 25 | 26 | System.out.println(map.keySet()); 27 | System.out.println(map.entrySet()); 28 | 29 | assertEquals(map.entrySet().size(), map.size()); 30 | assertFalse(map.containsKey("abcd")); 31 | assertEquals(map.get("abc"), "111"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/util/StringHelperTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util; 2 | 3 | import cn.hutool.core.util.RandomUtil; 4 | import junit.framework.TestCase; 5 | 6 | public class StringHelperTest extends TestCase { 7 | 8 | public void testHyphenate() { 9 | System.out.println(StringHelper.hyphenate("TEST999")); 10 | System.out.println(StringHelper.hyphenate("TEST999Id")); 11 | System.out.println(StringHelper.hyphenate("TEST999Name")); 12 | System.out.println(StringHelper.hyphenate("ishttp_Req")); 13 | System.out.println(StringHelper.hyphenate("ishttp_req")); 14 | System.out.println(StringHelper.hyphenate("ISHTTP_REQ")); 15 | System.out.println(StringHelper.hyphenate("Bp0B2")); 16 | System.out.println(StringHelper.hyphenate("IshttpReq")); 17 | System.out.println(StringHelper.hyphenate("isHttpReq")); 18 | System.out.println(StringHelper.hyphenate("isHTTPReq")); 19 | System.out.println(StringHelper.hyphenate("ISHTTPREQ")); 20 | System.out.println(StringHelper.hyphenate("_123A")); 21 | 22 | for (int i = 0; i < 100; i++) { 23 | String rnd = RandomUtil.randomString(20); 24 | String h1 = StringHelper.hyphenate(rnd).toLowerCase(); 25 | System.out.println(rnd + " > " + h1); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/java/cn/devezhao/persist4j/util/support/SchemaExportTest.java: -------------------------------------------------------------------------------- 1 | package cn.devezhao.persist4j.util.support; 2 | 3 | import cn.devezhao.persist4j.BaseTest; 4 | import cn.devezhao.persist4j.Entity; 5 | import cn.devezhao.persist4j.PersistManagerFactory; 6 | import cn.devezhao.persist4j.metadata.impl.ConfigurationMetadataFactory; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.dom4j.Element; 9 | import org.junit.Test; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * 15 | * @author zhaofang123@gmail.com 16 | * @since 02/27/2017 17 | */ 18 | public class SchemaExportTest extends BaseTest { 19 | 20 | @Test 21 | public void testExportDDL() throws Exception { 22 | PersistManagerFactory factory = getPersistManagerFactory(); 23 | 24 | SchemaExport schemaExport = new SchemaExport( 25 | factory.getMetadataFactory(), factory.getDialect(), factory.getDataSource().getConnection()); 26 | schemaExport.export(true, false); 27 | } 28 | 29 | @Test 30 | public void testGenDDL() throws Exception { 31 | PersistManagerFactory factory = getPersistManagerFactory(); 32 | 33 | Element cfgRoot = ((ConfigurationMetadataFactory) factory.getMetadataFactory()).getConfigDocument().getRootElement(); 34 | Entity entity = factory.getMetadataFactory().getEntity("TestAllType"); 35 | List ix = cfgRoot.selectSingleNode("//entity[@name='" + entity.getName() + "']").selectNodes("index"); 36 | 37 | String[] sqls = new Table(entity, factory.getDialect(), ix).generateDDL(false, false); 38 | System.out.println(StringUtils.join(sqls, "\n")); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/resources/metadata-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | --------------------------------------------------------------------------------