├── .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 | [](https://jitpack.io/#devezhao/persist4j)
4 | [](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 |
14 |
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 |
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 |
14 |
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 |
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 |
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 |
14 |
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 |
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 |
14 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
14 |
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 |
14 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/deprecated-list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 已过时的列表 (persist4j)
8 |
9 |
10 |
11 |
12 |
13 |
23 |
26 |
27 |
44 |
71 |
72 |
79 |
98 |
99 |
116 |
117 |
118 | - 上一个
119 | - 下一个
120 |
121 |
125 |
128 |
129 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | persist4j
8 |
60 |
61 |
75 |
76 |
--------------------------------------------------------------------------------
/docs/overview-frame.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 概览列表 (persist4j)
8 |
9 |
10 |
11 |
12 |
13 |
14 |
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 extends String, ? extends V> 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 extends String, ? extends V> 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