├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── finalteam │ │ └── sqlitefinalsample │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── finalteam │ │ └── sqlitefinalsample │ │ └── MainActivity.java │ └── res │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ └── values │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── downloads ├── SQLiteFinal-1.0.0-release.jar ├── SQLiteFinal-1.0.1-release.jar └── SQLiteFinal-1.0.3-release.jar ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── sqlitefinal ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── cn │ └── finalteam │ └── sqlitefinal │ └── ApplicationTest.java ├── main ├── AndroidManifest.xml └── java │ └── cn │ └── finalteam │ └── sqlitefinal │ ├── DbHelper.java │ ├── DbUpgradeListener.java │ ├── annotation │ ├── Check.java │ ├── Column.java │ ├── Finder.java │ ├── Foreign.java │ ├── Id.java │ ├── NoAutoIncrement.java │ ├── NotNull.java │ ├── Table.java │ ├── Transient.java │ └── Unique.java │ ├── converter │ ├── BooleanColumnConverter.java │ ├── ByteArrayColumnConverter.java │ ├── ByteColumnConverter.java │ ├── CharColumnConverter.java │ ├── ColumnConverter.java │ ├── ColumnConverterFactory.java │ ├── DateColumnConverter.java │ ├── DoubleColumnConverter.java │ ├── FloatColumnConverter.java │ ├── IntegerColumnConverter.java │ ├── LongColumnConverter.java │ ├── ShortColumnConverter.java │ ├── SqlDateColumnConverter.java │ └── StringColumnConverter.java │ ├── exception │ ├── BaseException.java │ └── DbException.java │ ├── sqlite │ ├── ColumnDbType.java │ ├── CursorUtils.java │ ├── DbModelSelector.java │ ├── FinderLazyLoader.java │ ├── ForeignLazyLoader.java │ ├── Selector.java │ ├── SqlInfo.java │ ├── SqlInfoBuilder.java │ └── WhereBuilder.java │ ├── table │ ├── Column.java │ ├── ColumnUtils.java │ ├── DbModel.java │ ├── Finder.java │ ├── Foreign.java │ ├── Id.java │ ├── KeyValue.java │ ├── Table.java │ └── TableUtils.java │ └── utils │ └── IOUtils.java └── test └── java └── cn └── finalteam └── sqlitefinal └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | # Created by https://www.gitignore.io 9 | 10 | ### Android ### 11 | # Built application files 12 | *.apk 13 | *.ap_ 14 | 15 | # Files for the Dalvik VM 16 | *.dex 17 | 18 | # Java class files 19 | *.class 20 | 21 | # Generated files 22 | bin/ 23 | gen/ 24 | 25 | # Gradle files 26 | .gradle/ 27 | build/ 28 | /*/build/ 29 | 30 | # Local configuration file (sdk path, etc) 31 | local.properties 32 | 33 | # Proguard folder generated by Eclipse 34 | proguard/ 35 | 36 | # Log Files 37 | *.log 38 | 39 | 40 | ### Gradle ### 41 | .gradle 42 | build/ 43 | 44 | # Ignore Gradle GUI config 45 | gradle-app.setting 46 | 47 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 48 | !gradle-wrapper.jar 49 | 50 | 51 | # Created by https://www.gitignore.io 52 | 53 | ### Intellij ### 54 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 55 | 56 | *.iml 57 | app.iml 58 | ## Directory-based project format: 59 | .idea/ 60 | # if you remove the above rule, at least ignore the following: 61 | 62 | # User-specific stuff: 63 | # .idea/workspace.xml 64 | # .idea/tasks.xml 65 | # .idea/dictionaries 66 | 67 | # Sensitive or high-churn files: 68 | # .idea/dataSources.ids 69 | # .idea/dataSources.xml 70 | # .idea/sqlDataSources.xml 71 | # .idea/dynamic.xml 72 | # .idea/uiDesigner.xml 73 | 74 | # Gradle: 75 | # .idea/gradle.xml 76 | # .idea/libraries 77 | 78 | # Mongo Explorer plugin: 79 | # .idea/mongoSettings.xml 80 | 81 | ## File-based project format: 82 | *.ipr 83 | *.iws 84 | 85 | ## Plugin-specific files: 86 | 87 | # IntelliJ 88 | out/ 89 | 90 | # mpeltonen/sbt-idea plugin 91 | .idea_modules/ 92 | 93 | # JIRA plugin 94 | atlassian-ide-plugin.xml 95 | 96 | # Crashlytics plugin (for Android Studio and IntelliJ) 97 | com_crashlytics_export_strings.xml 98 | crashlytics.properties 99 | crashlytics-build.properties 100 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #SQLiteFinal简介 2 | SQLite ORM 库,本项目是从[xUtils](https://github.com/wyouflf/xUtils)分解出来的 3 | ###我们后续要做以下工作 4 | * 数据库表字段动态更新 5 | * 支持更多的数据类型 6 | * 更详细的使用文档 7 | * ... 8 | 9 | -------- 10 | ###下载SQLiteFinal 11 | 下载这个[JAR](https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/master/downloads/) 或者通过Gradle抓取: 12 | 13 | ```groovy 14 | compile 'cn.finalteam:sqlitefinal:1.0.3' 15 | ``` 16 | 17 | ###DbHelper基本功能: 18 | * android中的orm框架,一行代码就可以进行增删改查; 19 | * 支持事务,默认关闭; 20 | * 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名); 21 | * 支持绑定外键,保存实体时外键关联实体自动保存或更新; 22 | * 自动加载外键关联实体,支持延时加载; 23 | * 支持链式表达查询,更直观的查询语义,参考下面的介绍或sample中的例子。 24 | 25 | ---- 26 | ###DbHelper使用方法:(后面会持续更新) 27 | 28 | ```java 29 | DbHelper db = DbHelper.create(this); 30 | User user = new User(); //这里需要注意的是User对象必须有id属性,或者有通过@ID注解的属性 31 | user.setEmail("wyouflf@qq.com"); 32 | user.setName("wyouflf"); 33 | db.save(user); // 使用saveBindingId保存实体时会为实体的id赋值 34 | 35 | ... 36 | // 查找 37 | Parent entity = db.findById(Parent.class, parent.getId()); 38 | List list = db.findAll(Parent.class);//通过类型查找 39 | 40 | Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","=","test")); 41 | 42 | // IS NULL 43 | Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","=", null)); 44 | // IS NOT NULL 45 | Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","!=", null)); 46 | 47 | // WHERE id<54 AND (age>20 OR age<30) ORDER BY id LIMIT pageSize OFFSET pageOffset 48 | List list = db.findAll(Selector.from(Parent.class) 49 | .where("id" ,"<", 54) 50 | .and(WhereBuilder.b("age", ">", 20).or("age", " < ", 30)) 51 | .orderBy("id") 52 | .limit(pageSize) 53 | .offset(pageSize * pageIndex)); 54 | 55 | // op为"in"时,最后一个参数必须是数组或Iterable的实现类(例如List等) 56 | Parent test = db.findFirst(Selector.from(Parent.class).where("id", "in", new int[]{1, 2, 3})); 57 | // op为"between"时,最后一个参数必须是数组或Iterable的实现类(例如List等) 58 | Parent test = db.findFirst(Selector.from(Parent.class).where("id", "between", new String[]{"1", "5"})); 59 | 60 | DbModel dbModel = db.findDbModelAll(Selector.from(Parent.class).select("name"));//select("name")只取出name列 61 | List dbModels = db.findDbModelAll(Selector.from(Parent.class).groupBy("name").select("name", "count(name)")); 62 | ... 63 | 64 | List dbModels = db.findDbModelAll(sql); // 自定义sql查询 65 | db.execNonQuery(sql) // 执行自定义sql 66 | ... 67 | 68 | ``` 69 | #混淆时注意事项: 70 | * 添加Android默认混淆配置${sdk.dir}/tools/proguard/proguard-android.txt 71 | * 不要混淆xUtils中的注解类型,添加混淆配置:-keep class * extends java.lang.annotation.Annotation { *; } 72 | * 对使用DbUtils模块持久化的实体类不要混淆,或者注解所有表和列名称@Table(name="xxx"),@Id(column="xxx"),@Column(column="xxx"),@Foreign(column="xxx",foreign="xxx"); 73 | 74 | 75 | License 76 | ------- 77 | 78 | Licensed under the Apache License, Version 2.0 (the "License"); 79 | you may not use this file except in compliance with the License. 80 | You may obtain a copy of the License at 81 | 82 | http://www.apache.org/licenses/LICENSE-2.0 83 | 84 | Unless required by applicable law or agreed to in writing, software 85 | distributed under the License is distributed on an "AS IS" BASIS, 86 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 87 | See the License for the specific language governing permissions and 88 | limitations under the License. 89 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | # Created by https://www.gitignore.io 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | 19 | # Gradle files 20 | .gradle/ 21 | build/ 22 | /*/build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | 34 | ### Gradle ### 35 | .gradle 36 | build/ 37 | 38 | # Ignore Gradle GUI config 39 | gradle-app.setting 40 | 41 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 42 | !gradle-wrapper.jar 43 | 44 | 45 | # Created by https://www.gitignore.io 46 | 47 | ### Intellij ### 48 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 49 | 50 | *.iml 51 | app.iml 52 | ## Directory-based project format: 53 | .idea/ 54 | # if you remove the above rule, at least ignore the following: 55 | 56 | # User-specific stuff: 57 | # .idea/workspace.xml 58 | # .idea/tasks.xml 59 | # .idea/dictionaries 60 | 61 | # Sensitive or high-churn files: 62 | # .idea/dataSources.ids 63 | # .idea/dataSources.xml 64 | # .idea/sqlDataSources.xml 65 | # .idea/dynamic.xml 66 | # .idea/uiDesigner.xml 67 | 68 | # Gradle: 69 | # .idea/gradle.xml 70 | # .idea/libraries 71 | 72 | # Mongo Explorer plugin: 73 | # .idea/mongoSettings.xml 74 | 75 | ## File-based project format: 76 | *.ipr 77 | *.iws 78 | 79 | ## Plugin-specific files: 80 | 81 | # IntelliJ 82 | out/ 83 | 84 | # mpeltonen/sbt-idea plugin 85 | .idea_modules/ 86 | 87 | # JIRA plugin 88 | atlassian-ide-plugin.xml 89 | 90 | # Crashlytics plugin (for Android Studio and IntelliJ) 91 | com_crashlytics_export_strings.xml 92 | crashlytics.properties 93 | crashlytics-build.properties 94 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.0 rc3" 6 | 7 | defaultConfig { 8 | applicationId "cn.finalteam.sqlitefinalsample" 9 | minSdkVersion 8 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.2.1' 25 | } 26 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/pengjianbo/Documents/dev/android_dev/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/finalteam/sqlitefinalsample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinalsample; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/cn/finalteam/sqlitefinalsample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinalsample; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | /** 7 | * Desction: 8 | * Author:pengjianbo 9 | * Date:15/9/17 下午3:53 10 | */ 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SQLiteFinalSample 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.0' 9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.3.1' 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /downloads/SQLiteFinal-1.0.0-release.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/downloads/SQLiteFinal-1.0.0-release.jar -------------------------------------------------------------------------------- /downloads/SQLiteFinal-1.0.1-release.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/downloads/SQLiteFinal-1.0.1-release.jar -------------------------------------------------------------------------------- /downloads/SQLiteFinal-1.0.3-release.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/downloads/SQLiteFinal-1.0.3-release.jar -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | #project 21 | #项目名称 22 | project_name=SQLiteFinal 23 | #项目组ID,通常情况下如果你的包名为com.example.test,那么项目组ID就是com.example 24 | project_groupId=cn.finalteam 25 | #项目ID,通常情况下如果你的包名为com.example.test,那么项目ID就是test 26 | project_artifactId=sqlitefinal 27 | #包类型,Android库是aar 28 | project_packaging=aar 29 | #项目版本 30 | project_version=1.0.3 31 | #项目官方网站的地址,没有的话就用Github上的地址 32 | project_siteUrl=https://github.com/pengjianbo/SQLiteFinal 33 | #项目的Git地址 34 | project_gitUrl=https://github.com/pengjianbo/SQLiteFinal.git 35 | 36 | #javadoc 37 | #生成的javadoc打开后主页显示的名称,通常跟项目名称一样即可 38 | javadoc_name=SQLiteFinal 39 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengjianbo/SQLiteFinal/e331baa81880fa1f4cc6cc4a0106f46172b6b8fa/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Sep 17 15:42:24 CST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':sqlitefinal' 2 | -------------------------------------------------------------------------------- /sqlitefinal/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sqlitefinal/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 8 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName project_version 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | } 24 | apply from: 'https://raw.githubusercontent.com/pengjianbo/ToolsFinal/master/bintray.gradle' 25 | -------------------------------------------------------------------------------- /sqlitefinal/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/pengjianbo/Documents/dev/android_dev/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sqlitefinal/src/androidTest/java/cn/finalteam/sqlitefinal/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /sqlitefinal/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/DbHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal; 17 | 18 | import android.content.Context; 19 | import android.database.Cursor; 20 | import android.database.sqlite.SQLiteDatabase; 21 | import android.text.TextUtils; 22 | import cn.finalteam.sqlitefinal.exception.DbException; 23 | import cn.finalteam.sqlitefinal.sqlite.CursorUtils; 24 | import cn.finalteam.sqlitefinal.sqlite.DbModelSelector; 25 | import cn.finalteam.sqlitefinal.sqlite.Selector; 26 | import cn.finalteam.sqlitefinal.sqlite.SqlInfo; 27 | import cn.finalteam.sqlitefinal.sqlite.SqlInfoBuilder; 28 | import cn.finalteam.sqlitefinal.sqlite.WhereBuilder; 29 | import cn.finalteam.sqlitefinal.table.DbModel; 30 | import cn.finalteam.sqlitefinal.table.Id; 31 | import cn.finalteam.sqlitefinal.table.Table; 32 | import cn.finalteam.sqlitefinal.table.TableUtils; 33 | import cn.finalteam.sqlitefinal.utils.IOUtils; 34 | import java.io.File; 35 | import java.util.ArrayList; 36 | import java.util.HashMap; 37 | import java.util.List; 38 | import java.util.concurrent.ConcurrentHashMap; 39 | import java.util.concurrent.locks.Lock; 40 | import java.util.concurrent.locks.ReentrantLock; 41 | 42 | public class DbHelper { 43 | 44 | //*************************************** create instance **************************************************** 45 | 46 | /** 47 | * key: dbName 48 | */ 49 | private static HashMap daoMap = new HashMap<>(); 50 | 51 | private SQLiteDatabase database; 52 | private DaoConfig daoConfig; 53 | private boolean debug = false; 54 | private boolean allowTransaction = false; 55 | 56 | private DbHelper(DaoConfig config) { 57 | if (config == null) { 58 | throw new IllegalArgumentException("daoConfig may not be null"); 59 | } 60 | this.database = createDatabase(config); 61 | this.daoConfig = config; 62 | } 63 | 64 | 65 | private synchronized static DbHelper getInstance(DaoConfig daoConfig) { 66 | DbHelper dao = daoMap.get(daoConfig.getDbName()); 67 | if (dao == null) { 68 | dao = new DbHelper(daoConfig); 69 | daoMap.put(daoConfig.getDbName(), dao); 70 | } else { 71 | dao.daoConfig = daoConfig; 72 | } 73 | 74 | // update the database if needed 75 | SQLiteDatabase database = dao.database; 76 | int oldVersion = database.getVersion(); 77 | int newVersion = daoConfig.getDbVersion(); 78 | if (oldVersion != newVersion) { 79 | if (oldVersion != 0) { 80 | DbUpgradeListener upgradeListener = daoConfig.getDbUpgradeListener(); 81 | if (upgradeListener != null) { 82 | upgradeListener.onUpgrade(dao, oldVersion, newVersion); 83 | } else { 84 | try { 85 | dao.dropDb(); 86 | } catch (DbException e) { 87 | //Logger.e(e.getMessage(), e); 88 | } 89 | } 90 | } 91 | database.setVersion(newVersion); 92 | } 93 | 94 | return dao; 95 | } 96 | 97 | public static DbHelper create(Context context) { 98 | DaoConfig config = new DaoConfig(context); 99 | return getInstance(config); 100 | } 101 | 102 | public static DbHelper create(Context context, String dbName) { 103 | DaoConfig config = new DaoConfig(context); 104 | config.setDbName(dbName); 105 | return getInstance(config); 106 | } 107 | 108 | public static DbHelper create(Context context, String dbDir, String dbName) { 109 | DaoConfig config = new DaoConfig(context); 110 | config.setDbDir(dbDir); 111 | config.setDbName(dbName); 112 | return getInstance(config); 113 | } 114 | 115 | public static DbHelper create(Context context, String dbName, int dbVersion, DbUpgradeListener dbUpgradeListener) { 116 | DaoConfig config = new DaoConfig(context); 117 | config.setDbName(dbName); 118 | config.setDbVersion(dbVersion); 119 | config.setDbUpgradeListener(dbUpgradeListener); 120 | return getInstance(config); 121 | } 122 | 123 | public static DbHelper create(Context context, String dbDir, String dbName, int dbVersion, DbUpgradeListener dbUpgradeListener) { 124 | DaoConfig config = new DaoConfig(context); 125 | config.setDbDir(dbDir); 126 | config.setDbName(dbName); 127 | config.setDbVersion(dbVersion); 128 | config.setDbUpgradeListener(dbUpgradeListener); 129 | return getInstance(config); 130 | } 131 | 132 | public static DbHelper create(DaoConfig daoConfig) { 133 | return getInstance(daoConfig); 134 | } 135 | 136 | public DbHelper configDebug(boolean debug) { 137 | this.debug = debug; 138 | return this; 139 | } 140 | 141 | public DbHelper configAllowTransaction(boolean allowTransaction) { 142 | this.allowTransaction = allowTransaction; 143 | return this; 144 | } 145 | 146 | public SQLiteDatabase getDatabase() { 147 | return database; 148 | } 149 | 150 | public DaoConfig getDaoConfig() { 151 | return daoConfig; 152 | } 153 | 154 | //*********************************************** operations ******************************************************** 155 | 156 | public void saveOrUpdate(Object entity) throws DbException { 157 | try { 158 | beginTransaction(); 159 | 160 | createTableIfNotExist(entity.getClass()); 161 | saveOrUpdateWithoutTransaction(entity); 162 | 163 | setTransactionSuccessful(); 164 | } finally { 165 | endTransaction(); 166 | } 167 | } 168 | 169 | public void saveOrUpdateAll(List entities) throws DbException { 170 | if (entities == null || entities.size() == 0) return; 171 | try { 172 | beginTransaction(); 173 | 174 | createTableIfNotExist(entities.get(0).getClass()); 175 | for (Object entity : entities) { 176 | saveOrUpdateWithoutTransaction(entity); 177 | } 178 | 179 | setTransactionSuccessful(); 180 | } finally { 181 | endTransaction(); 182 | } 183 | } 184 | 185 | public void replace(Object entity) throws DbException { 186 | try { 187 | beginTransaction(); 188 | 189 | createTableIfNotExist(entity.getClass()); 190 | execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(this, entity)); 191 | 192 | setTransactionSuccessful(); 193 | } finally { 194 | endTransaction(); 195 | } 196 | } 197 | 198 | public void replaceAll(List entities) throws DbException { 199 | if (entities == null || entities.size() == 0) return; 200 | try { 201 | beginTransaction(); 202 | 203 | createTableIfNotExist(entities.get(0).getClass()); 204 | for (Object entity : entities) { 205 | execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(this, entity)); 206 | } 207 | 208 | setTransactionSuccessful(); 209 | } finally { 210 | endTransaction(); 211 | } 212 | } 213 | 214 | public void save(Object entity) throws DbException { 215 | try { 216 | beginTransaction(); 217 | 218 | createTableIfNotExist(entity.getClass()); 219 | execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity)); 220 | 221 | setTransactionSuccessful(); 222 | } finally { 223 | endTransaction(); 224 | } 225 | } 226 | 227 | public void saveAll(List entities) throws DbException { 228 | if (entities == null || entities.size() == 0) return; 229 | try { 230 | beginTransaction(); 231 | 232 | createTableIfNotExist(entities.get(0).getClass()); 233 | for (Object entity : entities) { 234 | execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity)); 235 | } 236 | 237 | setTransactionSuccessful(); 238 | } finally { 239 | endTransaction(); 240 | } 241 | } 242 | 243 | public boolean saveBindingId(Object entity) throws DbException { 244 | boolean result = false; 245 | try { 246 | beginTransaction(); 247 | 248 | createTableIfNotExist(entity.getClass()); 249 | result = saveBindingIdWithoutTransaction(entity); 250 | 251 | setTransactionSuccessful(); 252 | } finally { 253 | endTransaction(); 254 | } 255 | return result; 256 | } 257 | 258 | public void saveBindingIdAll(List entities) throws DbException { 259 | if (entities == null || entities.size() == 0) return; 260 | try { 261 | beginTransaction(); 262 | 263 | createTableIfNotExist(entities.get(0).getClass()); 264 | for (Object entity : entities) { 265 | if (!saveBindingIdWithoutTransaction(entity)) { 266 | throw new DbException("saveBindingId error, transaction will not commit!"); 267 | } 268 | } 269 | 270 | setTransactionSuccessful(); 271 | } finally { 272 | endTransaction(); 273 | } 274 | } 275 | 276 | public void deleteById(Class entityType, Object idValue) throws DbException { 277 | if (!tableIsExist(entityType)) return; 278 | try { 279 | beginTransaction(); 280 | 281 | execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, idValue)); 282 | 283 | setTransactionSuccessful(); 284 | } finally { 285 | endTransaction(); 286 | } 287 | } 288 | 289 | public void delete(Object entity) throws DbException { 290 | if (!tableIsExist(entity.getClass())) return; 291 | try { 292 | beginTransaction(); 293 | 294 | execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entity)); 295 | 296 | setTransactionSuccessful(); 297 | } finally { 298 | endTransaction(); 299 | } 300 | } 301 | 302 | public void delete(Class entityType, WhereBuilder whereBuilder) throws DbException { 303 | if (!tableIsExist(entityType)) return; 304 | try { 305 | beginTransaction(); 306 | 307 | execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, whereBuilder)); 308 | 309 | setTransactionSuccessful(); 310 | } finally { 311 | endTransaction(); 312 | } 313 | } 314 | 315 | public void deleteAll(List entities) throws DbException { 316 | if (entities == null || entities.size() == 0 || !tableIsExist(entities.get(0).getClass())) return; 317 | try { 318 | beginTransaction(); 319 | 320 | for (Object entity : entities) { 321 | execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entity)); 322 | } 323 | 324 | setTransactionSuccessful(); 325 | } finally { 326 | endTransaction(); 327 | } 328 | } 329 | 330 | public void deleteAll(Class entityType) throws DbException { 331 | delete(entityType, null); 332 | } 333 | 334 | public void update(Object entity, String... updateColumnNames) throws DbException { 335 | if (!tableIsExist(entity.getClass())) return; 336 | try { 337 | beginTransaction(); 338 | 339 | execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames)); 340 | 341 | setTransactionSuccessful(); 342 | } finally { 343 | endTransaction(); 344 | } 345 | } 346 | 347 | public void update(Object entity, WhereBuilder whereBuilder, String... updateColumnNames) throws DbException { 348 | if (!tableIsExist(entity.getClass())) return; 349 | try { 350 | beginTransaction(); 351 | 352 | execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, whereBuilder, updateColumnNames)); 353 | 354 | setTransactionSuccessful(); 355 | } finally { 356 | endTransaction(); 357 | } 358 | } 359 | 360 | public void updateAll(List entities, String... updateColumnNames) throws DbException { 361 | if (entities == null || entities.size() == 0 || !tableIsExist(entities.get(0).getClass())) return; 362 | try { 363 | beginTransaction(); 364 | 365 | for (Object entity : entities) { 366 | execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames)); 367 | } 368 | 369 | setTransactionSuccessful(); 370 | } finally { 371 | endTransaction(); 372 | } 373 | } 374 | 375 | public void updateAll(List entities, WhereBuilder whereBuilder, String... updateColumnNames) throws DbException { 376 | if (entities == null || entities.size() == 0 || !tableIsExist(entities.get(0).getClass())) return; 377 | try { 378 | beginTransaction(); 379 | 380 | for (Object entity : entities) { 381 | execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, whereBuilder, updateColumnNames)); 382 | } 383 | 384 | setTransactionSuccessful(); 385 | } finally { 386 | endTransaction(); 387 | } 388 | } 389 | 390 | @SuppressWarnings("unchecked") 391 | public T findById(Class entityType, Object idValue) throws DbException { 392 | if (!tableIsExist(entityType)) return null; 393 | 394 | Table table = Table.get(this, entityType); 395 | Selector selector = Selector.from(entityType).where(table.id.getColumnName(), "=", idValue); 396 | 397 | String sql = selector.limit(1).toString(); 398 | long seq = CursorUtils.FindCacheSequence.getSeq(); 399 | findTempCache.setSeq(seq); 400 | Object obj = findTempCache.get(sql); 401 | if (obj != null) { 402 | return (T) obj; 403 | } 404 | 405 | Cursor cursor = execQuery(sql); 406 | if (cursor != null) { 407 | try { 408 | if (cursor.moveToNext()) { 409 | T entity = (T) CursorUtils.getEntity(this, cursor, entityType, seq); 410 | findTempCache.put(sql, entity); 411 | return entity; 412 | } 413 | } catch (Throwable e) { 414 | throw new DbException(e); 415 | } finally { 416 | IOUtils.closeQuietly(cursor); 417 | } 418 | } 419 | return null; 420 | } 421 | 422 | @SuppressWarnings("unchecked") 423 | public T findFirst(Selector selector) throws DbException { 424 | if (!tableIsExist(selector.getEntityType())) return null; 425 | 426 | String sql = selector.limit(1).toString(); 427 | long seq = CursorUtils.FindCacheSequence.getSeq(); 428 | findTempCache.setSeq(seq); 429 | Object obj = findTempCache.get(sql); 430 | if (obj != null) { 431 | return (T) obj; 432 | } 433 | 434 | Cursor cursor = execQuery(sql); 435 | if (cursor != null) { 436 | try { 437 | if (cursor.moveToNext()) { 438 | T entity = (T) CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq); 439 | findTempCache.put(sql, entity); 440 | return entity; 441 | } 442 | } catch (Throwable e) { 443 | throw new DbException(e); 444 | } finally { 445 | IOUtils.closeQuietly(cursor); 446 | } 447 | } 448 | return null; 449 | } 450 | 451 | public T findFirst(Class entityType) throws DbException { 452 | return findFirst(Selector.from(entityType)); 453 | } 454 | 455 | @SuppressWarnings("unchecked") 456 | public List findAll(Selector selector) throws DbException { 457 | if (!tableIsExist(selector.getEntityType())) return null; 458 | 459 | String sql = selector.toString(); 460 | long seq = CursorUtils.FindCacheSequence.getSeq(); 461 | findTempCache.setSeq(seq); 462 | Object obj = findTempCache.get(sql); 463 | if (obj != null) { 464 | return (List) obj; 465 | } 466 | 467 | List result = new ArrayList(); 468 | 469 | Cursor cursor = execQuery(sql); 470 | if (cursor != null) { 471 | try { 472 | while (cursor.moveToNext()) { 473 | T entity = (T) CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq); 474 | result.add(entity); 475 | } 476 | findTempCache.put(sql, result); 477 | } catch (Throwable e) { 478 | throw new DbException(e); 479 | } finally { 480 | IOUtils.closeQuietly(cursor); 481 | } 482 | } 483 | return result; 484 | } 485 | 486 | public List findAll(Class entityType) throws DbException { 487 | return findAll(Selector.from(entityType)); 488 | } 489 | 490 | public DbModel findDbModelFirst(SqlInfo sqlInfo) throws DbException { 491 | Cursor cursor = execQuery(sqlInfo); 492 | if (cursor != null) { 493 | try { 494 | if (cursor.moveToNext()) { 495 | return CursorUtils.getDbModel(cursor); 496 | } 497 | } catch (Throwable e) { 498 | throw new DbException(e); 499 | } finally { 500 | IOUtils.closeQuietly(cursor); 501 | } 502 | } 503 | return null; 504 | } 505 | 506 | public DbModel findDbModelFirst(DbModelSelector selector) throws DbException { 507 | if (!tableIsExist(selector.getEntityType())) return null; 508 | 509 | Cursor cursor = execQuery(selector.limit(1).toString()); 510 | if (cursor != null) { 511 | try { 512 | if (cursor.moveToNext()) { 513 | return CursorUtils.getDbModel(cursor); 514 | } 515 | } catch (Throwable e) { 516 | throw new DbException(e); 517 | } finally { 518 | IOUtils.closeQuietly(cursor); 519 | } 520 | } 521 | return null; 522 | } 523 | 524 | public List findDbModelAll(SqlInfo sqlInfo) throws DbException { 525 | List dbModelList = new ArrayList(); 526 | 527 | Cursor cursor = execQuery(sqlInfo); 528 | if (cursor != null) { 529 | try { 530 | while (cursor.moveToNext()) { 531 | dbModelList.add(CursorUtils.getDbModel(cursor)); 532 | } 533 | } catch (Throwable e) { 534 | throw new DbException(e); 535 | } finally { 536 | IOUtils.closeQuietly(cursor); 537 | } 538 | } 539 | return dbModelList; 540 | } 541 | 542 | public List findDbModelAll(DbModelSelector selector) throws DbException { 543 | if (!tableIsExist(selector.getEntityType())) return null; 544 | 545 | List dbModelList = new ArrayList(); 546 | 547 | Cursor cursor = execQuery(selector.toString()); 548 | if (cursor != null) { 549 | try { 550 | while (cursor.moveToNext()) { 551 | dbModelList.add(CursorUtils.getDbModel(cursor)); 552 | } 553 | } catch (Throwable e) { 554 | throw new DbException(e); 555 | } finally { 556 | IOUtils.closeQuietly(cursor); 557 | } 558 | } 559 | return dbModelList; 560 | } 561 | 562 | public long count(Selector selector) throws DbException { 563 | Class entityType = selector.getEntityType(); 564 | if (!tableIsExist(entityType)) return 0; 565 | 566 | Table table = Table.get(this, entityType); 567 | DbModelSelector dmSelector = selector.select("count(" + table.id.getColumnName() + ") as count"); 568 | return findDbModelFirst(dmSelector).getLong("count"); 569 | } 570 | 571 | public long count(Class entityType) throws DbException { 572 | return count(Selector.from(entityType)); 573 | } 574 | 575 | //******************************************** config ****************************************************** 576 | 577 | public static class DaoConfig { 578 | private Context context; 579 | private String dbName = "xUtils.db"; // default db name 580 | private int dbVersion = 1; 581 | private DbUpgradeListener dbUpgradeListener; 582 | 583 | private String dbDir; 584 | 585 | public DaoConfig(Context context) { 586 | this.context = context.getApplicationContext(); 587 | } 588 | 589 | public Context getContext() { 590 | return context; 591 | } 592 | 593 | public String getDbName() { 594 | return dbName; 595 | } 596 | 597 | public void setDbName(String dbName) { 598 | if (!TextUtils.isEmpty(dbName)) { 599 | this.dbName = dbName; 600 | } 601 | } 602 | 603 | public int getDbVersion() { 604 | return dbVersion; 605 | } 606 | 607 | public void setDbVersion(int dbVersion) { 608 | this.dbVersion = dbVersion; 609 | } 610 | 611 | public DbUpgradeListener getDbUpgradeListener() { 612 | return dbUpgradeListener; 613 | } 614 | 615 | public void setDbUpgradeListener(DbUpgradeListener dbUpgradeListener) { 616 | this.dbUpgradeListener = dbUpgradeListener; 617 | } 618 | 619 | public String getDbDir() { 620 | return dbDir; 621 | } 622 | 623 | /** 624 | * set database dir 625 | * 626 | * @param dbDir If dbDir is null or empty, use the app default db dir. 627 | */ 628 | public void setDbDir(String dbDir) { 629 | this.dbDir = dbDir; 630 | } 631 | } 632 | 633 | private SQLiteDatabase createDatabase(DaoConfig config) { 634 | SQLiteDatabase result = null; 635 | 636 | String dbDir = config.getDbDir(); 637 | if (!TextUtils.isEmpty(dbDir)) { 638 | File dir = new File(dbDir); 639 | if (dir.exists() || dir.mkdirs()) { 640 | File dbFile = new File(dbDir, config.getDbName()); 641 | result = SQLiteDatabase.openOrCreateDatabase(dbFile, null); 642 | } 643 | } else { 644 | result = config.getContext().openOrCreateDatabase(config.getDbName(), 0, null); 645 | } 646 | return result; 647 | } 648 | 649 | //***************************** private operations with out transaction ***************************** 650 | private void saveOrUpdateWithoutTransaction(Object entity) throws DbException { 651 | Table table = Table.get(this, entity.getClass()); 652 | Id id = table.id; 653 | if (id.isAutoIncrement()) { 654 | if (id.getColumnValue(entity) != null) { 655 | execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity)); 656 | } else { 657 | saveBindingIdWithoutTransaction(entity); 658 | } 659 | } else { 660 | execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(this, entity)); 661 | } 662 | } 663 | 664 | private boolean saveBindingIdWithoutTransaction(Object entity) throws DbException { 665 | Class entityType = entity.getClass(); 666 | Table table = Table.get(this, entityType); 667 | Id idColumn = table.id; 668 | if (idColumn.isAutoIncrement()) { 669 | execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity)); 670 | long id = getLastAutoIncrementId(table.tableName); 671 | if (id == -1) { 672 | return false; 673 | } 674 | idColumn.setAutoIncrementId(entity, id); 675 | return true; 676 | } else { 677 | execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity)); 678 | return true; 679 | } 680 | } 681 | 682 | //************************************************ tools *********************************** 683 | 684 | private long getLastAutoIncrementId(String tableName) throws DbException { 685 | long id = -1; 686 | Cursor cursor = execQuery("SELECT seq FROM sqlite_sequence WHERE name='" + tableName + "'"); 687 | if (cursor != null) { 688 | try { 689 | if (cursor.moveToNext()) { 690 | id = cursor.getLong(0); 691 | } 692 | } catch (Throwable e) { 693 | throw new DbException(e); 694 | } finally { 695 | IOUtils.closeQuietly(cursor); 696 | } 697 | } 698 | return id; 699 | } 700 | 701 | public void createTableIfNotExist(Class entityType) throws DbException { 702 | if (!tableIsExist(entityType)) { 703 | SqlInfo sqlInfo = SqlInfoBuilder.buildCreateTableSqlInfo(this, entityType); 704 | execNonQuery(sqlInfo); 705 | String execAfterTableCreated = TableUtils.getExecAfterTableCreated(entityType); 706 | if (!TextUtils.isEmpty(execAfterTableCreated)) { 707 | execNonQuery(execAfterTableCreated); 708 | } 709 | } 710 | } 711 | 712 | public boolean tableIsExist(Class entityType) throws DbException { 713 | Table table = Table.get(this, entityType); 714 | if (table.isCheckedDatabase()) { 715 | return true; 716 | } 717 | 718 | Cursor cursor = execQuery("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='" + table.tableName + "'"); 719 | if (cursor != null) { 720 | try { 721 | if (cursor.moveToNext()) { 722 | int count = cursor.getInt(0); 723 | if (count > 0) { 724 | table.setCheckedDatabase(true); 725 | return true; 726 | } 727 | } 728 | } catch (Throwable e) { 729 | throw new DbException(e); 730 | } finally { 731 | IOUtils.closeQuietly(cursor); 732 | } 733 | } 734 | 735 | return false; 736 | } 737 | 738 | public void dropDb() throws DbException { 739 | Cursor cursor = execQuery("SELECT name FROM sqlite_master WHERE type='table' AND name<>'sqlite_sequence'"); 740 | if (cursor != null) { 741 | try { 742 | while (cursor.moveToNext()) { 743 | try { 744 | String tableName = cursor.getString(0); 745 | execNonQuery("DROP TABLE " + tableName); 746 | Table.remove(this, tableName); 747 | } catch (Throwable e) { 748 | //Logger.e(e.getMessage(), e); 749 | } 750 | } 751 | 752 | } catch (Throwable e) { 753 | throw new DbException(e); 754 | } finally { 755 | IOUtils.closeQuietly(cursor); 756 | } 757 | } 758 | } 759 | 760 | public void dropTable(Class entityType) throws DbException { 761 | if (!tableIsExist(entityType)) return; 762 | String tableName = TableUtils.getTableName(entityType); 763 | execNonQuery("DROP TABLE " + tableName); 764 | Table.remove(this, entityType); 765 | } 766 | 767 | public void close() { 768 | String dbName = this.daoConfig.getDbName(); 769 | if (daoMap.containsKey(dbName)) { 770 | daoMap.remove(dbName); 771 | this.database.close(); 772 | } 773 | } 774 | 775 | ///////////////////////////////////// exec sql ///////////////////////////////////////////////////// 776 | private void debugSql(String sql) { 777 | if (debug) { 778 | //Logger.d(sql); 779 | } 780 | } 781 | 782 | private Lock writeLock = new ReentrantLock(); 783 | private volatile boolean writeLocked = false; 784 | 785 | private void beginTransaction() { 786 | if (allowTransaction) { 787 | database.beginTransaction(); 788 | } else { 789 | writeLock.lock(); 790 | writeLocked = true; 791 | } 792 | } 793 | 794 | private void setTransactionSuccessful() { 795 | if (allowTransaction) { 796 | database.setTransactionSuccessful(); 797 | } 798 | } 799 | 800 | private void endTransaction() { 801 | if (allowTransaction) { 802 | database.endTransaction(); 803 | } 804 | if (writeLocked) { 805 | writeLock.unlock(); 806 | writeLocked = false; 807 | } 808 | } 809 | 810 | 811 | public void execNonQuery(SqlInfo sqlInfo) throws DbException { 812 | debugSql(sqlInfo.getSql()); 813 | try { 814 | if (sqlInfo.getBindArgs() != null) { 815 | database.execSQL(sqlInfo.getSql(), sqlInfo.getBindArgsAsArray()); 816 | } else { 817 | database.execSQL(sqlInfo.getSql()); 818 | } 819 | } catch (Throwable e) { 820 | throw new DbException(e); 821 | } 822 | } 823 | 824 | public void execNonQuery(String sql) throws DbException { 825 | debugSql(sql); 826 | try { 827 | database.execSQL(sql); 828 | } catch (Throwable e) { 829 | throw new DbException(e); 830 | } 831 | } 832 | 833 | public Cursor execQuery(SqlInfo sqlInfo) throws DbException { 834 | debugSql(sqlInfo.getSql()); 835 | try { 836 | return database.rawQuery(sqlInfo.getSql(), sqlInfo.getBindArgsAsStrArray()); 837 | } catch (Throwable e) { 838 | throw new DbException(e); 839 | } 840 | } 841 | 842 | public Cursor execQuery(String sql) throws DbException { 843 | debugSql(sql); 844 | try { 845 | return database.rawQuery(sql, null); 846 | } catch (Throwable e) { 847 | throw new DbException(e); 848 | } 849 | } 850 | 851 | /////////////////////// temp cache //////////////////////////////////////////////////////////////// 852 | private final FindTempCache findTempCache = new FindTempCache(); 853 | 854 | private class FindTempCache { 855 | private FindTempCache() { 856 | } 857 | 858 | /** 859 | * key: sql; 860 | * value: find result 861 | */ 862 | private final ConcurrentHashMap cache = new ConcurrentHashMap(); 863 | 864 | private long seq = 0; 865 | 866 | public void put(String sql, Object result) { 867 | if (sql != null && result != null) { 868 | cache.put(sql, result); 869 | } 870 | } 871 | 872 | public Object get(String sql) { 873 | return cache.get(sql); 874 | } 875 | 876 | public void setSeq(long seq) { 877 | if (this.seq != seq) { 878 | cache.clear(); 879 | this.seq = seq; 880 | } 881 | } 882 | } 883 | 884 | } 885 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/DbUpgradeListener.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal; 2 | 3 | /** 4 | * Desction:数据库更新事件 5 | * Author:pengjianbo 6 | * Date:15/7/6 上午10:36 7 | */ 8 | public interface DbUpgradeListener { 9 | public void onUpgrade(DbHelper db, int oldVersion, int newVersion); 10 | } 11 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Check.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Author: wyouflf 25 | * Date: 13-8-20 26 | * Time: 上午9:44 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | public @interface Check { 31 | String value(); 32 | } 33 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Column.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | @Target(ElementType.FIELD) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface Column { 26 | 27 | String column() default ""; 28 | 29 | String defaultValue() default ""; 30 | } 31 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Finder.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Author: wyouflf 10 | * Date: 13-9-10 11 | * Time: 下午6:44 12 | */ 13 | @Target(ElementType.FIELD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Finder { 16 | 17 | String valueColumn(); 18 | 19 | String targetColumn(); 20 | } 21 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Foreign.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | @Target(ElementType.FIELD) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface Foreign { 26 | 27 | String column() default ""; 28 | 29 | String foreign(); 30 | } 31 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Id.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | @Target(ElementType.FIELD) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface Id { 26 | String column() default ""; 27 | } 28 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/NoAutoIncrement.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Author: wyouflf 10 | * Date: 13-9-24 11 | * Time: 上午9:33 12 | */ 13 | @Target(ElementType.FIELD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface NoAutoIncrement { 16 | } 17 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/NotNull.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Author: wyouflf 25 | * Date: 13-8-20 26 | * Time: 上午9:42 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | public @interface NotNull { 31 | } 32 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Table.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | @Target(ElementType.TYPE) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface Table { 26 | 27 | String name() default ""; 28 | 29 | String execAfterTableCreated() default ""; 30 | } -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Transient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | @Target(ElementType.FIELD) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | public @interface Transient { 26 | } 27 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/annotation/Unique.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.annotation; 17 | 18 | import java.lang.annotation.ElementType; 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.annotation.Target; 22 | 23 | /** 24 | * Author: wyouflf 25 | * Date: 13-8-20 26 | * Time: 上午9:41 27 | */ 28 | @Target(ElementType.FIELD) 29 | @Retention(RetentionPolicy.RUNTIME) 30 | public @interface Unique { 31 | } 32 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/BooleanColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class BooleanColumnConverter implements ColumnConverter { 13 | @Override 14 | public Boolean getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getInt(index) == 1; 16 | } 17 | 18 | @Override 19 | public Boolean getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return fieldStringValue.length() == 1 ? "1".equals(fieldStringValue) : Boolean.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Boolean fieldValue) { 26 | if (fieldValue == null) return null; 27 | return fieldValue ? 1 : 0; 28 | } 29 | 30 | @Override 31 | public ColumnDbType getColumnDbType() { 32 | return ColumnDbType.INTEGER; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/ByteArrayColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 5 | 6 | /** 7 | * Author: wyouflf 8 | * Date: 13-11-4 9 | * Time: 下午10:51 10 | */ 11 | public class ByteArrayColumnConverter implements ColumnConverter { 12 | @Override 13 | public byte[] getFieldValue(final Cursor cursor, int index) { 14 | return cursor.isNull(index) ? null : cursor.getBlob(index); 15 | } 16 | 17 | @Override 18 | public byte[] getFieldValue(String fieldStringValue) { 19 | return null; 20 | } 21 | 22 | @Override 23 | public Object fieldValue2ColumnValue(byte[] fieldValue) { 24 | return fieldValue; 25 | } 26 | 27 | @Override 28 | public ColumnDbType getColumnDbType() { 29 | return ColumnDbType.BLOB; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/ByteColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class ByteColumnConverter implements ColumnConverter { 13 | @Override 14 | public Byte getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : (byte) cursor.getInt(index); 16 | } 17 | 18 | @Override 19 | public Byte getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Byte.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Byte fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.INTEGER; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/CharColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class CharColumnConverter implements ColumnConverter { 13 | @Override 14 | public Character getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : (char) cursor.getInt(index); 16 | } 17 | 18 | @Override 19 | public Character getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return fieldStringValue.charAt(0); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Character fieldValue) { 26 | if (fieldValue == null) return null; 27 | return (int) fieldValue; 28 | } 29 | 30 | @Override 31 | public ColumnDbType getColumnDbType() { 32 | return ColumnDbType.INTEGER; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/ColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 5 | 6 | /** 7 | * Author: wyouflf 8 | * Date: 13-11-4 9 | * Time: 下午8:57 10 | */ 11 | public interface ColumnConverter { 12 | 13 | T getFieldValue(final Cursor cursor, int index); 14 | 15 | T getFieldValue(String fieldStringValue); 16 | 17 | Object fieldValue2ColumnValue(T fieldValue); 18 | 19 | ColumnDbType getColumnDbType(); 20 | } 21 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/ColumnConverterFactory.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 4 | import java.util.Date; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:27 11 | */ 12 | public class ColumnConverterFactory { 13 | 14 | private ColumnConverterFactory() { 15 | } 16 | 17 | public static ColumnConverter getColumnConverter(Class columnType) { 18 | if (columnType_columnConverter_map.containsKey(columnType.getName())) { 19 | return columnType_columnConverter_map.get(columnType.getName()); 20 | } else if (ColumnConverter.class.isAssignableFrom(columnType)) { 21 | try { 22 | ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance(); 23 | if (columnConverter != null) { 24 | columnType_columnConverter_map.put(columnType.getName(), columnConverter); 25 | } 26 | return columnConverter; 27 | } catch (Throwable e) { 28 | } 29 | } 30 | return null; 31 | } 32 | 33 | public static ColumnDbType getDbColumnType(Class columnType) { 34 | ColumnConverter converter = getColumnConverter(columnType); 35 | if (converter != null) { 36 | return converter.getColumnDbType(); 37 | } 38 | return ColumnDbType.TEXT; 39 | } 40 | 41 | public static void registerColumnConverter(Class columnType, ColumnConverter columnConverter) { 42 | columnType_columnConverter_map.put(columnType.getName(), columnConverter); 43 | } 44 | 45 | public static boolean isSupportColumnConverter(Class columnType) { 46 | if (columnType_columnConverter_map.containsKey(columnType.getName())) { 47 | return true; 48 | } else if (ColumnConverter.class.isAssignableFrom(columnType)) { 49 | try { 50 | ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance(); 51 | if (columnConverter != null) { 52 | columnType_columnConverter_map.put(columnType.getName(), columnConverter); 53 | } 54 | return columnConverter == null; 55 | } catch (Throwable e) { 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | private static final ConcurrentHashMap columnType_columnConverter_map; 62 | 63 | static { 64 | columnType_columnConverter_map = new ConcurrentHashMap(); 65 | 66 | BooleanColumnConverter booleanColumnConverter = new BooleanColumnConverter(); 67 | columnType_columnConverter_map.put(boolean.class.getName(), booleanColumnConverter); 68 | columnType_columnConverter_map.put(Boolean.class.getName(), booleanColumnConverter); 69 | 70 | ByteArrayColumnConverter byteArrayColumnConverter = new ByteArrayColumnConverter(); 71 | columnType_columnConverter_map.put(byte[].class.getName(), byteArrayColumnConverter); 72 | 73 | ByteColumnConverter byteColumnConverter = new ByteColumnConverter(); 74 | columnType_columnConverter_map.put(byte.class.getName(), byteColumnConverter); 75 | columnType_columnConverter_map.put(Byte.class.getName(), byteColumnConverter); 76 | 77 | CharColumnConverter charColumnConverter = new CharColumnConverter(); 78 | columnType_columnConverter_map.put(char.class.getName(), charColumnConverter); 79 | columnType_columnConverter_map.put(Character.class.getName(), charColumnConverter); 80 | 81 | DateColumnConverter dateColumnConverter = new DateColumnConverter(); 82 | columnType_columnConverter_map.put(Date.class.getName(), dateColumnConverter); 83 | 84 | DoubleColumnConverter doubleColumnConverter = new DoubleColumnConverter(); 85 | columnType_columnConverter_map.put(double.class.getName(), doubleColumnConverter); 86 | columnType_columnConverter_map.put(Double.class.getName(), doubleColumnConverter); 87 | 88 | FloatColumnConverter floatColumnConverter = new FloatColumnConverter(); 89 | columnType_columnConverter_map.put(float.class.getName(), floatColumnConverter); 90 | columnType_columnConverter_map.put(Float.class.getName(), floatColumnConverter); 91 | 92 | IntegerColumnConverter integerColumnConverter = new IntegerColumnConverter(); 93 | columnType_columnConverter_map.put(int.class.getName(), integerColumnConverter); 94 | columnType_columnConverter_map.put(Integer.class.getName(), integerColumnConverter); 95 | 96 | LongColumnConverter longColumnConverter = new LongColumnConverter(); 97 | columnType_columnConverter_map.put(long.class.getName(), longColumnConverter); 98 | columnType_columnConverter_map.put(Long.class.getName(), longColumnConverter); 99 | 100 | ShortColumnConverter shortColumnConverter = new ShortColumnConverter(); 101 | columnType_columnConverter_map.put(short.class.getName(), shortColumnConverter); 102 | columnType_columnConverter_map.put(Short.class.getName(), shortColumnConverter); 103 | 104 | SqlDateColumnConverter sqlDateColumnConverter = new SqlDateColumnConverter(); 105 | columnType_columnConverter_map.put(java.sql.Date.class.getName(), sqlDateColumnConverter); 106 | 107 | StringColumnConverter stringColumnConverter = new StringColumnConverter(); 108 | columnType_columnConverter_map.put(String.class.getName(), stringColumnConverter); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/DateColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | import java.util.Date; 7 | 8 | /** 9 | * Author: wyouflf 10 | * Date: 13-11-4 11 | * Time: 下午10:51 12 | */ 13 | public class DateColumnConverter implements ColumnConverter { 14 | @Override 15 | public Date getFieldValue(final Cursor cursor, int index) { 16 | return cursor.isNull(index) ? null : new Date(cursor.getLong(index)); 17 | } 18 | 19 | @Override 20 | public Date getFieldValue(String fieldStringValue) { 21 | if (TextUtils.isEmpty(fieldStringValue)) return null; 22 | return new Date(Long.valueOf(fieldStringValue)); 23 | } 24 | 25 | @Override 26 | public Object fieldValue2ColumnValue(Date fieldValue) { 27 | if (fieldValue == null) return null; 28 | return fieldValue.getTime(); 29 | } 30 | 31 | @Override 32 | public ColumnDbType getColumnDbType() { 33 | return ColumnDbType.INTEGER; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/DoubleColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class DoubleColumnConverter implements ColumnConverter { 13 | @Override 14 | public Double getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getDouble(index); 16 | } 17 | 18 | @Override 19 | public Double getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Double.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Double fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.REAL; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/FloatColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class FloatColumnConverter implements ColumnConverter { 13 | @Override 14 | public Float getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getFloat(index); 16 | } 17 | 18 | @Override 19 | public Float getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Float.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Float fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.REAL; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/IntegerColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class IntegerColumnConverter implements ColumnConverter { 13 | @Override 14 | public Integer getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getInt(index); 16 | } 17 | 18 | @Override 19 | public Integer getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Integer.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Integer fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.INTEGER; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/LongColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class LongColumnConverter implements ColumnConverter { 13 | @Override 14 | public Long getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getLong(index); 16 | } 17 | 18 | @Override 19 | public Long getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Long.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Long fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.INTEGER; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/ShortColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class ShortColumnConverter implements ColumnConverter { 13 | @Override 14 | public Short getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : cursor.getShort(index); 16 | } 17 | 18 | @Override 19 | public Short getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return Short.valueOf(fieldStringValue); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(Short fieldValue) { 26 | return fieldValue; 27 | } 28 | 29 | @Override 30 | public ColumnDbType getColumnDbType() { 31 | return ColumnDbType.INTEGER; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/SqlDateColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import android.text.TextUtils; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | 7 | /** 8 | * Author: wyouflf 9 | * Date: 13-11-4 10 | * Time: 下午10:51 11 | */ 12 | public class SqlDateColumnConverter implements ColumnConverter { 13 | @Override 14 | public java.sql.Date getFieldValue(final Cursor cursor, int index) { 15 | return cursor.isNull(index) ? null : new java.sql.Date(cursor.getLong(index)); 16 | } 17 | 18 | @Override 19 | public java.sql.Date getFieldValue(String fieldStringValue) { 20 | if (TextUtils.isEmpty(fieldStringValue)) return null; 21 | return new java.sql.Date(Long.valueOf(fieldStringValue)); 22 | } 23 | 24 | @Override 25 | public Object fieldValue2ColumnValue(java.sql.Date fieldValue) { 26 | if (fieldValue == null) return null; 27 | return fieldValue.getTime(); 28 | } 29 | 30 | @Override 31 | public ColumnDbType getColumnDbType() { 32 | return ColumnDbType.INTEGER; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/converter/StringColumnConverter.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.converter; 2 | 3 | import android.database.Cursor; 4 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 5 | 6 | /** 7 | * Author: wyouflf 8 | * Date: 13-11-4 9 | * Time: 下午10:51 10 | */ 11 | public class StringColumnConverter implements ColumnConverter { 12 | @Override 13 | public String getFieldValue(final Cursor cursor, int index) { 14 | return cursor.isNull(index) ? null : cursor.getString(index); 15 | } 16 | 17 | @Override 18 | public String getFieldValue(String fieldStringValue) { 19 | return fieldStringValue; 20 | } 21 | 22 | @Override 23 | public Object fieldValue2ColumnValue(String fieldValue) { 24 | return fieldValue; 25 | } 26 | 27 | @Override 28 | public ColumnDbType getColumnDbType() { 29 | return ColumnDbType.TEXT; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.exception; 17 | 18 | /** 19 | * Author: wyouflf 20 | * Date: 13-7-24 21 | * Time: 下午3:00 22 | */ 23 | public class BaseException extends Exception { 24 | private static final long serialVersionUID = 1L; 25 | 26 | public BaseException() { 27 | } 28 | 29 | public BaseException(String detailMessage) { 30 | super(detailMessage); 31 | } 32 | 33 | public BaseException(String detailMessage, Throwable throwable) { 34 | super(detailMessage, throwable); 35 | } 36 | 37 | public BaseException(Throwable throwable) { 38 | super(throwable); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/exception/DbException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.exception; 17 | 18 | public class DbException extends BaseException { 19 | private static final long serialVersionUID = 1L; 20 | 21 | public DbException() { 22 | } 23 | 24 | public DbException(String detailMessage) { 25 | super(detailMessage); 26 | } 27 | 28 | public DbException(String detailMessage, Throwable throwable) { 29 | super(detailMessage, throwable); 30 | } 31 | 32 | public DbException(Throwable throwable) { 33 | super(throwable); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/ColumnDbType.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.sqlite; 2 | 3 | /** 4 | * Created by wyouflf on 14-2-20. 5 | */ 6 | public enum ColumnDbType { 7 | 8 | INTEGER("INTEGER"), REAL("REAL"), TEXT("TEXT"), BLOB("BLOB"); 9 | 10 | private String value; 11 | 12 | ColumnDbType(String value) { 13 | this.value = value; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return value; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/CursorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import android.database.Cursor; 19 | import cn.finalteam.sqlitefinal.DbHelper; 20 | import cn.finalteam.sqlitefinal.table.Column; 21 | import cn.finalteam.sqlitefinal.table.DbModel; 22 | import cn.finalteam.sqlitefinal.table.Finder; 23 | import cn.finalteam.sqlitefinal.table.Id; 24 | import cn.finalteam.sqlitefinal.table.Table; 25 | import java.util.concurrent.ConcurrentHashMap; 26 | 27 | public class CursorUtils { 28 | 29 | @SuppressWarnings("unchecked") 30 | public static T getEntity(final DbHelper db, final Cursor cursor, Class entityType, long findCacheSequence) { 31 | if (db == null || cursor == null) return null; 32 | 33 | EntityTempCache.setSeq(findCacheSequence); 34 | try { 35 | Table table = Table.get(db, entityType); 36 | Id id = table.id; 37 | String idColumnName = id.getColumnName(); 38 | int idIndex = id.getIndex(); 39 | if (idIndex < 0) { 40 | idIndex = cursor.getColumnIndex(idColumnName); 41 | } 42 | Object idValue = id.getColumnConverter().getFieldValue(cursor, idIndex); 43 | T entity = EntityTempCache.get(entityType, idValue); 44 | if (entity == null) { 45 | entity = entityType.newInstance(); 46 | id.setValue2Entity(entity, cursor, idIndex); 47 | EntityTempCache.put(entityType, idValue, entity); 48 | } else { 49 | return entity; 50 | } 51 | int columnCount = cursor.getColumnCount(); 52 | for (int i = 0; i < columnCount; i++) { 53 | String columnName = cursor.getColumnName(i); 54 | Column column = table.columnMap.get(columnName); 55 | if (column != null) { 56 | column.setValue2Entity(entity, cursor, i); 57 | } 58 | } 59 | 60 | // init finder 61 | for (Finder finder : table.finderMap.values()) { 62 | finder.setValue2Entity(entity, null, 0); 63 | } 64 | return entity; 65 | } catch (Throwable e) { 66 | //Logger.e(e.getMessage(), e); 67 | } 68 | 69 | return null; 70 | } 71 | 72 | public static DbModel getDbModel(final Cursor cursor) { 73 | DbModel result = null; 74 | if (cursor != null) { 75 | result = new DbModel(); 76 | int columnCount = cursor.getColumnCount(); 77 | for (int i = 0; i < columnCount; i++) { 78 | result.add(cursor.getColumnName(i), cursor.getString(i)); 79 | } 80 | } 81 | return result; 82 | } 83 | 84 | public static class FindCacheSequence { 85 | private FindCacheSequence() { 86 | } 87 | 88 | private static long seq = 0; 89 | private static final String FOREIGN_LAZY_LOADER_CLASS_NAME = ForeignLazyLoader.class.getName(); 90 | private static final String FINDER_LAZY_LOADER_CLASS_NAME = FinderLazyLoader.class.getName(); 91 | 92 | public static long getSeq() { 93 | String findMethodCaller = Thread.currentThread().getStackTrace()[4].getClassName(); 94 | if (!findMethodCaller.equals(FOREIGN_LAZY_LOADER_CLASS_NAME) && !findMethodCaller.equals(FINDER_LAZY_LOADER_CLASS_NAME)) { 95 | ++seq; 96 | } 97 | return seq; 98 | } 99 | } 100 | 101 | private static class EntityTempCache { 102 | private EntityTempCache() { 103 | } 104 | 105 | private static final ConcurrentHashMap cache = new ConcurrentHashMap(); 106 | 107 | private static long seq = 0; 108 | 109 | public static void put(Class entityType, Object idValue, Object entity) { 110 | cache.put(entityType.getName() + "#" + idValue, entity); 111 | } 112 | 113 | @SuppressWarnings("unchecked") 114 | public static T get(Class entityType, Object idValue) { 115 | return (T) cache.get(entityType.getName() + "#" + idValue); 116 | } 117 | 118 | public static void setSeq(long seq) { 119 | if (EntityTempCache.seq != seq) { 120 | cache.clear(); 121 | EntityTempCache.seq = seq; 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/DbModelSelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import android.text.TextUtils; 19 | 20 | /** 21 | * Author: wyouflf 22 | * Date: 13-8-10 23 | * Time: 下午2:15 24 | */ 25 | public class DbModelSelector { 26 | 27 | private String[] columnExpressions; 28 | private String groupByColumnName; 29 | private WhereBuilder having; 30 | 31 | private Selector selector; 32 | 33 | private DbModelSelector(Class entityType) { 34 | selector = Selector.from(entityType); 35 | } 36 | 37 | protected DbModelSelector(Selector selector, String groupByColumnName) { 38 | this.selector = selector; 39 | this.groupByColumnName = groupByColumnName; 40 | } 41 | 42 | protected DbModelSelector(Selector selector, String[] columnExpressions) { 43 | this.selector = selector; 44 | this.columnExpressions = columnExpressions; 45 | } 46 | 47 | public static DbModelSelector from(Class entityType) { 48 | return new DbModelSelector(entityType); 49 | } 50 | 51 | public DbModelSelector where(WhereBuilder whereBuilder) { 52 | selector.where(whereBuilder); 53 | return this; 54 | } 55 | 56 | public DbModelSelector where(String columnName, String op, Object value) { 57 | selector.where(columnName, op, value); 58 | return this; 59 | } 60 | 61 | public DbModelSelector and(String columnName, String op, Object value) { 62 | selector.and(columnName, op, value); 63 | return this; 64 | } 65 | 66 | public DbModelSelector and(WhereBuilder where) { 67 | selector.and(where); 68 | return this; 69 | } 70 | 71 | public DbModelSelector or(String columnName, String op, Object value) { 72 | selector.or(columnName, op, value); 73 | return this; 74 | } 75 | 76 | public DbModelSelector or(WhereBuilder where) { 77 | selector.or(where); 78 | return this; 79 | } 80 | 81 | public DbModelSelector expr(String expr) { 82 | selector.expr(expr); 83 | return this; 84 | } 85 | 86 | public DbModelSelector expr(String columnName, String op, Object value) { 87 | selector.expr(columnName, op, value); 88 | return this; 89 | } 90 | 91 | public DbModelSelector groupBy(String columnName) { 92 | this.groupByColumnName = columnName; 93 | return this; 94 | } 95 | 96 | public DbModelSelector having(WhereBuilder whereBuilder) { 97 | this.having = whereBuilder; 98 | return this; 99 | } 100 | 101 | public DbModelSelector select(String... columnExpressions) { 102 | this.columnExpressions = columnExpressions; 103 | return this; 104 | } 105 | 106 | public DbModelSelector orderBy(String columnName) { 107 | selector.orderBy(columnName); 108 | return this; 109 | } 110 | 111 | public DbModelSelector orderBy(String columnName, boolean desc) { 112 | selector.orderBy(columnName, desc); 113 | return this; 114 | } 115 | 116 | public DbModelSelector limit(int limit) { 117 | selector.limit(limit); 118 | return this; 119 | } 120 | 121 | public DbModelSelector offset(int offset) { 122 | selector.offset(offset); 123 | return this; 124 | } 125 | 126 | public Class getEntityType() { 127 | return selector.getEntityType(); 128 | } 129 | 130 | @Override 131 | public String toString() { 132 | StringBuffer result = new StringBuffer(); 133 | result.append("SELECT "); 134 | if (columnExpressions != null && columnExpressions.length > 0) { 135 | for (int i = 0; i < columnExpressions.length; i++) { 136 | result.append(columnExpressions[i]); 137 | result.append(","); 138 | } 139 | result.deleteCharAt(result.length() - 1); 140 | } else { 141 | if (!TextUtils.isEmpty(groupByColumnName)) { 142 | result.append(groupByColumnName); 143 | } else { 144 | result.append("*"); 145 | } 146 | } 147 | result.append(" FROM ").append(selector.tableName); 148 | if (selector.whereBuilder != null && selector.whereBuilder.getWhereItemSize() > 0) { 149 | result.append(" WHERE ").append(selector.whereBuilder.toString()); 150 | } 151 | if (!TextUtils.isEmpty(groupByColumnName)) { 152 | result.append(" GROUP BY ").append(groupByColumnName); 153 | if (having != null && having.getWhereItemSize() > 0) { 154 | result.append(" HAVING ").append(having.toString()); 155 | } 156 | } 157 | if (selector.orderByList != null) { 158 | for (int i = 0; i < selector.orderByList.size(); i++) { 159 | result.append(" ORDER BY ").append(selector.orderByList.get(i).toString()); 160 | } 161 | } 162 | if (selector.limit > 0) { 163 | result.append(" LIMIT ").append(selector.limit); 164 | result.append(" OFFSET ").append(selector.offset); 165 | } 166 | return result.toString(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/FinderLazyLoader.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.sqlite; 2 | 3 | import cn.finalteam.sqlitefinal.exception.DbException; 4 | import cn.finalteam.sqlitefinal.table.ColumnUtils; 5 | import cn.finalteam.sqlitefinal.table.Finder; 6 | import cn.finalteam.sqlitefinal.table.Table; 7 | import java.util.List; 8 | 9 | /** 10 | * Author: wyouflf 11 | * Date: 13-9-10 12 | * Time: 下午10:50 13 | */ 14 | public class FinderLazyLoader { 15 | private final Finder finderColumn; 16 | private final Object finderValue; 17 | 18 | public FinderLazyLoader(Finder finderColumn, Object value) { 19 | this.finderColumn = finderColumn; 20 | this.finderValue = ColumnUtils.convert2DbColumnValueIfNeeded(value); 21 | } 22 | 23 | public List getAllFromDb() throws DbException { 24 | List entities = null; 25 | Table table = finderColumn.getTable(); 26 | if (table != null) { 27 | entities = table.db.findAll( 28 | Selector.from(finderColumn.getTargetEntityType()). 29 | where(finderColumn.getTargetColumnName(), "=", finderValue) 30 | ); 31 | } 32 | return entities; 33 | } 34 | 35 | public T getFirstFromDb() throws DbException { 36 | T entity = null; 37 | Table table = finderColumn.getTable(); 38 | if (table != null) { 39 | entity = table.db.findFirst( 40 | Selector.from(finderColumn.getTargetEntityType()). 41 | where(finderColumn.getTargetColumnName(), "=", finderValue) 42 | ); 43 | } 44 | return entity; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/ForeignLazyLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import cn.finalteam.sqlitefinal.exception.DbException; 19 | import cn.finalteam.sqlitefinal.table.ColumnUtils; 20 | import cn.finalteam.sqlitefinal.table.Foreign; 21 | import cn.finalteam.sqlitefinal.table.Table; 22 | import java.util.List; 23 | 24 | public class ForeignLazyLoader { 25 | private final Foreign foreignColumn; 26 | private Object columnValue; 27 | 28 | public ForeignLazyLoader(Foreign foreignColumn, Object value) { 29 | this.foreignColumn = foreignColumn; 30 | this.columnValue = ColumnUtils.convert2DbColumnValueIfNeeded(value); 31 | } 32 | 33 | public List getAllFromDb() throws DbException { 34 | List entities = null; 35 | Table table = foreignColumn.getTable(); 36 | if (table != null) { 37 | entities = table.db.findAll( 38 | Selector.from(foreignColumn.getForeignEntityType()). 39 | where(foreignColumn.getForeignColumnName(), "=", columnValue) 40 | ); 41 | } 42 | return entities; 43 | } 44 | 45 | public T getFirstFromDb() throws DbException { 46 | T entity = null; 47 | Table table = foreignColumn.getTable(); 48 | if (table != null) { 49 | entity = table.db.findFirst( 50 | Selector.from(foreignColumn.getForeignEntityType()). 51 | where(foreignColumn.getForeignColumnName(), "=", columnValue) 52 | ); 53 | } 54 | return entity; 55 | } 56 | 57 | public void setColumnValue(Object value) { 58 | this.columnValue = ColumnUtils.convert2DbColumnValueIfNeeded(value); 59 | } 60 | 61 | public Object getColumnValue() { 62 | return columnValue; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/Selector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import cn.finalteam.sqlitefinal.table.TableUtils; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * Author: wyouflf 24 | * Date: 13-8-9 25 | * Time: 下午10:19 26 | */ 27 | public class Selector { 28 | 29 | protected Class entityType; 30 | protected String tableName; 31 | 32 | protected WhereBuilder whereBuilder; 33 | protected List orderByList; 34 | protected int limit = 0; 35 | protected int offset = 0; 36 | 37 | private Selector(Class entityType) { 38 | this.entityType = entityType; 39 | this.tableName = TableUtils.getTableName(entityType); 40 | } 41 | 42 | public static Selector from(Class entityType) { 43 | return new Selector(entityType); 44 | } 45 | 46 | public Selector where(WhereBuilder whereBuilder) { 47 | this.whereBuilder = whereBuilder; 48 | return this; 49 | } 50 | 51 | public Selector where(String columnName, String op, Object value) { 52 | this.whereBuilder = WhereBuilder.b(columnName, op, value); 53 | return this; 54 | } 55 | 56 | public Selector and(String columnName, String op, Object value) { 57 | this.whereBuilder.and(columnName, op, value); 58 | return this; 59 | } 60 | 61 | public Selector and(WhereBuilder where) { 62 | this.whereBuilder.expr("AND (" + where.toString() + ")"); 63 | return this; 64 | } 65 | 66 | public Selector or(String columnName, String op, Object value) { 67 | this.whereBuilder.or(columnName, op, value); 68 | return this; 69 | } 70 | 71 | public Selector or(WhereBuilder where) { 72 | this.whereBuilder.expr("OR (" + where.toString() + ")"); 73 | return this; 74 | } 75 | 76 | public Selector expr(String expr) { 77 | if (this.whereBuilder == null) { 78 | this.whereBuilder = WhereBuilder.b(); 79 | } 80 | this.whereBuilder.expr(expr); 81 | return this; 82 | } 83 | 84 | public Selector expr(String columnName, String op, Object value) { 85 | if (this.whereBuilder == null) { 86 | this.whereBuilder = WhereBuilder.b(); 87 | } 88 | this.whereBuilder.expr(columnName, op, value); 89 | return this; 90 | } 91 | 92 | public DbModelSelector groupBy(String columnName) { 93 | return new DbModelSelector(this, columnName); 94 | } 95 | 96 | public DbModelSelector select(String... columnExpressions) { 97 | return new DbModelSelector(this, columnExpressions); 98 | } 99 | 100 | public Selector orderBy(String columnName) { 101 | if (orderByList == null) { 102 | orderByList = new ArrayList(2); 103 | } 104 | orderByList.add(new OrderBy(columnName)); 105 | return this; 106 | } 107 | 108 | public Selector orderBy(String columnName, boolean desc) { 109 | if (orderByList == null) { 110 | orderByList = new ArrayList(2); 111 | } 112 | orderByList.add(new OrderBy(columnName, desc)); 113 | return this; 114 | } 115 | 116 | public Selector limit(int limit) { 117 | this.limit = limit; 118 | return this; 119 | } 120 | 121 | public Selector offset(int offset) { 122 | this.offset = offset; 123 | return this; 124 | } 125 | 126 | @Override 127 | public String toString() { 128 | StringBuilder result = new StringBuilder(); 129 | result.append("SELECT "); 130 | result.append("*"); 131 | result.append(" FROM ").append(tableName); 132 | if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) { 133 | result.append(" WHERE ").append(whereBuilder.toString()); 134 | } 135 | if (orderByList != null) { 136 | for (int i = 0; i < orderByList.size(); i++) { 137 | result.append(" ORDER BY ").append(orderByList.get(i).toString()); 138 | } 139 | } 140 | if (limit > 0) { 141 | result.append(" LIMIT ").append(limit); 142 | result.append(" OFFSET ").append(offset); 143 | } 144 | return result.toString(); 145 | } 146 | 147 | public Class getEntityType() { 148 | return entityType; 149 | } 150 | 151 | protected class OrderBy { 152 | private String columnName; 153 | private boolean desc; 154 | 155 | public OrderBy(String columnName) { 156 | this.columnName = columnName; 157 | } 158 | 159 | public OrderBy(String columnName, boolean desc) { 160 | this.columnName = columnName; 161 | this.desc = desc; 162 | } 163 | 164 | @Override 165 | public String toString() { 166 | return columnName + (desc ? " DESC" : " ASC"); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/SqlInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import cn.finalteam.sqlitefinal.table.ColumnUtils; 19 | import java.util.LinkedList; 20 | 21 | public class SqlInfo { 22 | 23 | private String sql; 24 | private LinkedList bindArgs; 25 | 26 | public SqlInfo() { 27 | } 28 | 29 | public SqlInfo(String sql) { 30 | this.sql = sql; 31 | } 32 | 33 | public SqlInfo(String sql, Object... bindArgs) { 34 | this.sql = sql; 35 | addBindArgs(bindArgs); 36 | } 37 | 38 | public String getSql() { 39 | return sql; 40 | } 41 | 42 | public void setSql(String sql) { 43 | this.sql = sql; 44 | } 45 | 46 | public LinkedList getBindArgs() { 47 | return bindArgs; 48 | } 49 | 50 | public Object[] getBindArgsAsArray() { 51 | if (bindArgs != null) { 52 | return bindArgs.toArray(); 53 | } 54 | return null; 55 | } 56 | 57 | public String[] getBindArgsAsStrArray() { 58 | if (bindArgs != null) { 59 | String[] strings = new String[bindArgs.size()]; 60 | for (int i = 0; i < bindArgs.size(); i++) { 61 | Object value = bindArgs.get(i); 62 | strings[i] = value == null ? null : value.toString(); 63 | } 64 | return strings; 65 | } 66 | return null; 67 | } 68 | 69 | public void addBindArg(Object arg) { 70 | if (bindArgs == null) { 71 | bindArgs = new LinkedList(); 72 | } 73 | 74 | bindArgs.add(ColumnUtils.convert2DbColumnValueIfNeeded(arg)); 75 | } 76 | 77 | /* package */ void addBindArgWithoutConverter(Object arg) { 78 | if (bindArgs == null) { 79 | bindArgs = new LinkedList(); 80 | } 81 | 82 | bindArgs.add(arg); 83 | } 84 | 85 | public void addBindArgs(Object... bindArgs) { 86 | if (bindArgs != null) { 87 | for (Object arg : bindArgs) { 88 | addBindArg(arg); 89 | } 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/SqlInfoBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import cn.finalteam.sqlitefinal.DbHelper; 19 | import cn.finalteam.sqlitefinal.exception.DbException; 20 | import cn.finalteam.sqlitefinal.table.Column; 21 | import cn.finalteam.sqlitefinal.table.ColumnUtils; 22 | import cn.finalteam.sqlitefinal.table.Finder; 23 | import cn.finalteam.sqlitefinal.table.Id; 24 | import cn.finalteam.sqlitefinal.table.KeyValue; 25 | import cn.finalteam.sqlitefinal.table.Table; 26 | import cn.finalteam.sqlitefinal.table.TableUtils; 27 | import java.util.ArrayList; 28 | import java.util.Collection; 29 | import java.util.Collections; 30 | import java.util.HashSet; 31 | import java.util.List; 32 | 33 | /** 34 | * Build "insert", "replace",,"update", "delete" and "create" sql. 35 | */ 36 | public class SqlInfoBuilder { 37 | 38 | private SqlInfoBuilder() { 39 | } 40 | 41 | //*********************************************** insert sql *********************************************** 42 | 43 | public static SqlInfo buildInsertSqlInfo(DbHelper db, Object entity) throws DbException { 44 | 45 | List keyValueList = entity2KeyValueList(db, entity); 46 | if (keyValueList.size() == 0) return null; 47 | 48 | SqlInfo result = new SqlInfo(); 49 | StringBuffer sqlBuffer = new StringBuffer(); 50 | 51 | sqlBuffer.append("INSERT INTO "); 52 | sqlBuffer.append(TableUtils.getTableName(entity.getClass())); 53 | sqlBuffer.append(" ("); 54 | for (KeyValue kv : keyValueList) { 55 | sqlBuffer.append(kv.key).append(","); 56 | result.addBindArgWithoutConverter(kv.value); 57 | } 58 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 59 | sqlBuffer.append(") VALUES ("); 60 | 61 | int length = keyValueList.size(); 62 | for (int i = 0; i < length; i++) { 63 | sqlBuffer.append("?,"); 64 | } 65 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 66 | sqlBuffer.append(")"); 67 | 68 | result.setSql(sqlBuffer.toString()); 69 | 70 | return result; 71 | } 72 | 73 | //*********************************************** replace sql *********************************************** 74 | 75 | public static SqlInfo buildReplaceSqlInfo(DbHelper db, Object entity) throws DbException { 76 | 77 | List keyValueList = entity2KeyValueList(db, entity); 78 | if (keyValueList.size() == 0) return null; 79 | 80 | SqlInfo result = new SqlInfo(); 81 | StringBuffer sqlBuffer = new StringBuffer(); 82 | 83 | sqlBuffer.append("REPLACE INTO "); 84 | sqlBuffer.append(TableUtils.getTableName(entity.getClass())); 85 | sqlBuffer.append(" ("); 86 | for (KeyValue kv : keyValueList) { 87 | sqlBuffer.append(kv.key).append(","); 88 | result.addBindArgWithoutConverter(kv.value); 89 | } 90 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 91 | sqlBuffer.append(") VALUES ("); 92 | 93 | int length = keyValueList.size(); 94 | for (int i = 0; i < length; i++) { 95 | sqlBuffer.append("?,"); 96 | } 97 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 98 | sqlBuffer.append(")"); 99 | 100 | result.setSql(sqlBuffer.toString()); 101 | 102 | return result; 103 | } 104 | 105 | //*********************************************** delete sql *********************************************** 106 | 107 | private static String buildDeleteSqlByTableName(String tableName) { 108 | return "DELETE FROM " + tableName; 109 | } 110 | 111 | public static SqlInfo buildDeleteSqlInfo(DbHelper db, Object entity) throws DbException { 112 | SqlInfo result = new SqlInfo(); 113 | 114 | Class entityType = entity.getClass(); 115 | Table table = Table.get(db, entityType); 116 | Id id = table.id; 117 | Object idValue = id.getColumnValue(entity); 118 | 119 | if (idValue == null) { 120 | throw new DbException("this entity[" + entity.getClass() + "]'s id value is null"); 121 | } 122 | StringBuilder sb = new StringBuilder(buildDeleteSqlByTableName(table.tableName)); 123 | sb.append(" WHERE ").append(WhereBuilder.b(id.getColumnName(), "=", idValue)); 124 | 125 | result.setSql(sb.toString()); 126 | 127 | return result; 128 | } 129 | 130 | public static SqlInfo buildDeleteSqlInfo(DbHelper db, Class entityType, Object idValue) throws DbException { 131 | SqlInfo result = new SqlInfo(); 132 | 133 | Table table = Table.get(db, entityType); 134 | Id id = table.id; 135 | 136 | if (null == idValue) { 137 | throw new DbException("this entity[" + entityType + "]'s id value is null"); 138 | } 139 | StringBuilder sb = new StringBuilder(buildDeleteSqlByTableName(table.tableName)); 140 | sb.append(" WHERE ").append(WhereBuilder.b(id.getColumnName(), "=", idValue)); 141 | 142 | result.setSql(sb.toString()); 143 | 144 | return result; 145 | } 146 | 147 | public static SqlInfo buildDeleteSqlInfo(DbHelper db, Class entityType, WhereBuilder whereBuilder) throws DbException { 148 | Table table = Table.get(db, entityType); 149 | StringBuilder sb = new StringBuilder(buildDeleteSqlByTableName(table.tableName)); 150 | 151 | if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) { 152 | sb.append(" WHERE ").append(whereBuilder.toString()); 153 | } 154 | 155 | return new SqlInfo(sb.toString()); 156 | } 157 | 158 | //*********************************************** update sql *********************************************** 159 | 160 | public static SqlInfo buildUpdateSqlInfo(DbHelper db, Object entity, String... updateColumnNames) throws DbException { 161 | 162 | List keyValueList = entity2KeyValueList(db, entity); 163 | if (keyValueList.size() == 0) return null; 164 | 165 | HashSet updateColumnNameSet = null; 166 | if (updateColumnNames != null && updateColumnNames.length > 0) { 167 | updateColumnNameSet = new HashSet(updateColumnNames.length); 168 | Collections.addAll(updateColumnNameSet, updateColumnNames); 169 | } 170 | 171 | Class entityType = entity.getClass(); 172 | Table table = Table.get(db, entityType); 173 | Id id = table.id; 174 | Object idValue = id.getColumnValue(entity); 175 | 176 | if (null == idValue) { 177 | throw new DbException("this entity[" + entity.getClass() + "]'s id value is null"); 178 | } 179 | 180 | SqlInfo result = new SqlInfo(); 181 | StringBuffer sqlBuffer = new StringBuffer("UPDATE "); 182 | sqlBuffer.append(table.tableName); 183 | sqlBuffer.append(" SET "); 184 | for (KeyValue kv : keyValueList) { 185 | if (updateColumnNameSet == null || updateColumnNameSet.contains(kv.key)) { 186 | sqlBuffer.append(kv.key).append("=?,"); 187 | result.addBindArgWithoutConverter(kv.value); 188 | } 189 | } 190 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 191 | sqlBuffer.append(" WHERE ").append(WhereBuilder.b(id.getColumnName(), "=", idValue)); 192 | 193 | result.setSql(sqlBuffer.toString()); 194 | return result; 195 | } 196 | 197 | public static SqlInfo buildUpdateSqlInfo(DbHelper db, Object entity, WhereBuilder whereBuilder, String... updateColumnNames) throws DbException { 198 | 199 | List keyValueList = entity2KeyValueList(db, entity); 200 | if (keyValueList.size() == 0) return null; 201 | 202 | HashSet updateColumnNameSet = null; 203 | if (updateColumnNames != null && updateColumnNames.length > 0) { 204 | updateColumnNameSet = new HashSet(updateColumnNames.length); 205 | Collections.addAll(updateColumnNameSet, updateColumnNames); 206 | } 207 | 208 | Class entityType = entity.getClass(); 209 | String tableName = TableUtils.getTableName(entityType); 210 | 211 | SqlInfo result = new SqlInfo(); 212 | StringBuffer sqlBuffer = new StringBuffer("UPDATE "); 213 | sqlBuffer.append(tableName); 214 | sqlBuffer.append(" SET "); 215 | for (KeyValue kv : keyValueList) { 216 | if (updateColumnNameSet == null || updateColumnNameSet.contains(kv.key)) { 217 | sqlBuffer.append(kv.key).append("=?,"); 218 | result.addBindArgWithoutConverter(kv.value); 219 | } 220 | } 221 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 222 | if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) { 223 | sqlBuffer.append(" WHERE ").append(whereBuilder.toString()); 224 | } 225 | 226 | result.setSql(sqlBuffer.toString()); 227 | return result; 228 | } 229 | 230 | //*********************************************** others *********************************************** 231 | 232 | public static SqlInfo buildCreateTableSqlInfo(DbHelper db, Class entityType) throws DbException { 233 | Table table = Table.get(db, entityType); 234 | Id id = table.id; 235 | 236 | StringBuffer sqlBuffer = new StringBuffer(); 237 | sqlBuffer.append("CREATE TABLE IF NOT EXISTS "); 238 | sqlBuffer.append(table.tableName); 239 | sqlBuffer.append(" ( "); 240 | 241 | if (id.isAutoIncrement()) { 242 | sqlBuffer.append("\"").append(id.getColumnName()).append("\" ").append("INTEGER PRIMARY KEY AUTOINCREMENT,"); 243 | } else { 244 | sqlBuffer.append("\"").append(id.getColumnName()).append("\" ").append(id.getColumnDbType()).append(" PRIMARY KEY,"); 245 | } 246 | 247 | Collection columns = table.columnMap.values(); 248 | for (Column column : columns) { 249 | if (column instanceof Finder) { 250 | continue; 251 | } 252 | sqlBuffer.append("\"").append(column.getColumnName()).append("\" "); 253 | sqlBuffer.append(column.getColumnDbType()); 254 | if (ColumnUtils.isUnique(column.getColumnField())) { 255 | sqlBuffer.append(" UNIQUE"); 256 | } 257 | if (ColumnUtils.isNotNull(column.getColumnField())) { 258 | sqlBuffer.append(" NOT NULL"); 259 | } 260 | String check = ColumnUtils.getCheck(column.getColumnField()); 261 | if (check != null) { 262 | sqlBuffer.append(" CHECK(").append(check).append(")"); 263 | } 264 | sqlBuffer.append(","); 265 | } 266 | 267 | sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); 268 | sqlBuffer.append(" )"); 269 | return new SqlInfo(sqlBuffer.toString()); 270 | } 271 | 272 | private static KeyValue column2KeyValue(Object entity, Column column) { 273 | KeyValue kv = null; 274 | String key = column.getColumnName(); 275 | if (key != null) { 276 | Object value = column.getColumnValue(entity); 277 | value = value == null ? column.getDefaultValue() : value; 278 | kv = new KeyValue(key, value); 279 | } 280 | return kv; 281 | } 282 | 283 | public static List entity2KeyValueList(DbHelper db, Object entity) { 284 | 285 | List keyValueList = new ArrayList(); 286 | 287 | Class entityType = entity.getClass(); 288 | Table table = Table.get(db, entityType); 289 | Id id = table.id; 290 | 291 | if (!id.isAutoIncrement()) { 292 | Object idValue = id.getColumnValue(entity); 293 | KeyValue kv = new KeyValue(id.getColumnName(), idValue); 294 | keyValueList.add(kv); 295 | } 296 | 297 | Collection columns = table.columnMap.values(); 298 | for (Column column : columns) { 299 | if (column instanceof Finder) { 300 | continue; 301 | } 302 | KeyValue kv = column2KeyValue(entity, column); 303 | if (kv != null) { 304 | keyValueList.add(kv); 305 | } 306 | } 307 | 308 | return keyValueList; 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/sqlite/WhereBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.sqlite; 17 | 18 | import android.text.TextUtils; 19 | import cn.finalteam.sqlitefinal.converter.ColumnConverterFactory; 20 | import cn.finalteam.sqlitefinal.table.ColumnUtils; 21 | import java.lang.reflect.Array; 22 | import java.util.ArrayList; 23 | import java.util.Iterator; 24 | import java.util.List; 25 | 26 | /** 27 | * Author: wyouflf 28 | * Date: 13-7-29 29 | * Time: 上午9:35 30 | */ 31 | public class WhereBuilder { 32 | 33 | private final List whereItems; 34 | 35 | private WhereBuilder() { 36 | this.whereItems = new ArrayList(); 37 | } 38 | 39 | /** 40 | * create new instance 41 | * 42 | * @return 43 | */ 44 | public static WhereBuilder b() { 45 | return new WhereBuilder(); 46 | } 47 | 48 | /** 49 | * create new instance 50 | * 51 | * @param columnName 52 | * @param op operator: "=","<","LIKE","IN","BETWEEN"... 53 | * @param value 54 | * @return 55 | */ 56 | public static WhereBuilder b(String columnName, String op, Object value) { 57 | WhereBuilder result = new WhereBuilder(); 58 | result.appendCondition(null, columnName, op, value); 59 | return result; 60 | } 61 | 62 | /** 63 | * add AND condition 64 | * 65 | * @param columnName 66 | * @param op operator: "=","<","LIKE","IN","BETWEEN"... 67 | * @param value 68 | * @return 69 | */ 70 | public WhereBuilder and(String columnName, String op, Object value) { 71 | appendCondition(whereItems.size() == 0 ? null : "AND", columnName, op, value); 72 | return this; 73 | } 74 | 75 | /** 76 | * add OR condition 77 | * 78 | * @param columnName 79 | * @param op operator: "=","<","LIKE","IN","BETWEEN"... 80 | * @param value 81 | * @return 82 | */ 83 | public WhereBuilder or(String columnName, String op, Object value) { 84 | appendCondition(whereItems.size() == 0 ? null : "OR", columnName, op, value); 85 | return this; 86 | } 87 | 88 | public WhereBuilder expr(String expr) { 89 | whereItems.add(" " + expr); 90 | return this; 91 | } 92 | 93 | public WhereBuilder expr(String columnName, String op, Object value) { 94 | appendCondition(null, columnName, op, value); 95 | return this; 96 | } 97 | 98 | public int getWhereItemSize() { 99 | return whereItems.size(); 100 | } 101 | 102 | @Override 103 | public String toString() { 104 | if (whereItems.size() == 0) { 105 | return ""; 106 | } 107 | StringBuilder sb = new StringBuilder(); 108 | for (String item : whereItems) { 109 | sb.append(item); 110 | } 111 | return sb.toString(); 112 | } 113 | 114 | private void appendCondition(String conj, String columnName, String op, Object value) { 115 | StringBuilder sqlSb = new StringBuilder(); 116 | 117 | if (whereItems.size() > 0) { 118 | sqlSb.append(" "); 119 | } 120 | 121 | // append conj 122 | if (!TextUtils.isEmpty(conj)) { 123 | sqlSb.append(conj + " "); 124 | } 125 | 126 | // append columnName 127 | sqlSb.append(columnName); 128 | 129 | // convert op 130 | if ("!=".equals(op)) { 131 | op = "<>"; 132 | } else if ("==".equals(op)) { 133 | op = "="; 134 | } 135 | 136 | // append op & value 137 | if (value == null) { 138 | if ("=".equals(op)) { 139 | sqlSb.append(" IS NULL"); 140 | } else if ("<>".equals(op)) { 141 | sqlSb.append(" IS NOT NULL"); 142 | } else { 143 | sqlSb.append(" " + op + " NULL"); 144 | } 145 | } else { 146 | sqlSb.append(" " + op + " "); 147 | 148 | if ("IN".equalsIgnoreCase(op)) { 149 | Iterable items = null; 150 | if (value instanceof Iterable) { 151 | items = (Iterable) value; 152 | } else if (value.getClass().isArray()) { 153 | ArrayList arrayList = new ArrayList(); 154 | int len = Array.getLength(value); 155 | for (int i = 0; i < len; i++) { 156 | arrayList.add(Array.get(value, i)); 157 | } 158 | items = arrayList; 159 | } 160 | if (items != null) { 161 | StringBuffer stringBuffer = new StringBuffer("("); 162 | for (Object item : items) { 163 | Object itemColValue = ColumnUtils.convert2DbColumnValueIfNeeded(item); 164 | if (ColumnDbType.TEXT.equals(ColumnConverterFactory.getDbColumnType(itemColValue.getClass()))) { 165 | String valueStr = itemColValue.toString(); 166 | if (valueStr.indexOf('\'') != -1) { // convert single quotations 167 | valueStr = valueStr.replace("'", "''"); 168 | } 169 | stringBuffer.append("'" + valueStr + "'"); 170 | } else { 171 | stringBuffer.append(itemColValue); 172 | } 173 | stringBuffer.append(","); 174 | } 175 | stringBuffer.deleteCharAt(stringBuffer.length() - 1); 176 | stringBuffer.append(")"); 177 | sqlSb.append(stringBuffer.toString()); 178 | } else { 179 | throw new IllegalArgumentException("value must be an Array or an Iterable."); 180 | } 181 | } else if ("BETWEEN".equalsIgnoreCase(op)) { 182 | Iterable items = null; 183 | if (value instanceof Iterable) { 184 | items = (Iterable) value; 185 | } else if (value.getClass().isArray()) { 186 | ArrayList arrayList = new ArrayList(); 187 | int len = Array.getLength(value); 188 | for (int i = 0; i < len; i++) { 189 | arrayList.add(Array.get(value, i)); 190 | } 191 | items = arrayList; 192 | } 193 | if (items != null) { 194 | Iterator iterator = items.iterator(); 195 | if (!iterator.hasNext()) throw new IllegalArgumentException("value must have tow items."); 196 | Object start = iterator.next(); 197 | if (!iterator.hasNext()) throw new IllegalArgumentException("value must have tow items."); 198 | Object end = iterator.next(); 199 | 200 | Object startColValue = ColumnUtils.convert2DbColumnValueIfNeeded(start); 201 | Object endColValue = ColumnUtils.convert2DbColumnValueIfNeeded(end); 202 | 203 | if (ColumnDbType.TEXT.equals(ColumnConverterFactory.getDbColumnType(startColValue.getClass()))) { 204 | String startStr = startColValue.toString(); 205 | if (startStr.indexOf('\'') != -1) { // convert single quotations 206 | startStr = startStr.replace("'", "''"); 207 | } 208 | String endStr = endColValue.toString(); 209 | if (endStr.indexOf('\'') != -1) { // convert single quotations 210 | endStr = endStr.replace("'", "''"); 211 | } 212 | sqlSb.append("'" + startStr + "'"); 213 | sqlSb.append(" AND "); 214 | sqlSb.append("'" + endStr + "'"); 215 | } else { 216 | sqlSb.append(startColValue); 217 | sqlSb.append(" AND "); 218 | sqlSb.append(endColValue); 219 | } 220 | } else { 221 | throw new IllegalArgumentException("value must be an Array or an Iterable."); 222 | } 223 | } else { 224 | value = ColumnUtils.convert2DbColumnValueIfNeeded(value); 225 | if (ColumnDbType.TEXT.equals(ColumnConverterFactory.getDbColumnType(value.getClass()))) { 226 | String valueStr = value.toString(); 227 | if (valueStr.indexOf('\'') != -1) { // convert single quotations 228 | valueStr = valueStr.replace("'", "''"); 229 | } 230 | sqlSb.append("'" + valueStr + "'"); 231 | } else { 232 | sqlSb.append(value); 233 | } 234 | } 235 | } 236 | whereItems.add(sqlSb.toString()); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/Column.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.database.Cursor; 19 | import cn.finalteam.sqlitefinal.converter.ColumnConverter; 20 | import cn.finalteam.sqlitefinal.converter.ColumnConverterFactory; 21 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 22 | import java.lang.reflect.Field; 23 | import java.lang.reflect.Method; 24 | 25 | public class Column { 26 | 27 | private Table table; 28 | 29 | private int index = -1; 30 | 31 | protected final String columnName; 32 | private final Object defaultValue; 33 | 34 | protected final Method getMethod; 35 | protected final Method setMethod; 36 | 37 | protected final Field columnField; 38 | protected final ColumnConverter columnConverter; 39 | 40 | /* package */ Column(Class entityType, Field field) { 41 | this.columnField = field; 42 | this.columnConverter = ColumnConverterFactory.getColumnConverter(field.getType()); 43 | this.columnName = ColumnUtils.getColumnNameByField(field); 44 | if (this.columnConverter != null) { 45 | this.defaultValue = this.columnConverter.getFieldValue(ColumnUtils.getColumnDefaultValue(field)); 46 | } else { 47 | this.defaultValue = null; 48 | } 49 | this.getMethod = ColumnUtils.getColumnGetMethod(entityType, field); 50 | this.setMethod = ColumnUtils.getColumnSetMethod(entityType, field); 51 | } 52 | 53 | @SuppressWarnings("unchecked") 54 | public void setValue2Entity(Object entity, Cursor cursor, int index) { 55 | this.index = index; 56 | Object value = columnConverter.getFieldValue(cursor, index); 57 | if (value == null && defaultValue == null) return; 58 | 59 | if (setMethod != null) { 60 | try { 61 | setMethod.invoke(entity, value == null ? defaultValue : value); 62 | } catch (Throwable e) { 63 | //Logger.e(e.getMessage(), e); 64 | } 65 | } else { 66 | try { 67 | this.columnField.setAccessible(true); 68 | this.columnField.set(entity, value == null ? defaultValue : value); 69 | } catch (Throwable e) { 70 | //Logger.e(e.getMessage(), e); 71 | } 72 | } 73 | } 74 | 75 | @SuppressWarnings("unchecked") 76 | public Object getColumnValue(Object entity) { 77 | Object fieldValue = getFieldValue(entity); 78 | return columnConverter.fieldValue2ColumnValue(fieldValue); 79 | } 80 | 81 | public Object getFieldValue(Object entity) { 82 | Object fieldValue = null; 83 | if (entity != null) { 84 | if (getMethod != null) { 85 | try { 86 | fieldValue = getMethod.invoke(entity); 87 | } catch (Throwable e) { 88 | //Logger.e(e.getMessage(), e); 89 | } 90 | } else { 91 | try { 92 | this.columnField.setAccessible(true); 93 | fieldValue = this.columnField.get(entity); 94 | } catch (Throwable e) { 95 | //Logger.e(e.getMessage(), e); 96 | } 97 | } 98 | } 99 | return fieldValue; 100 | } 101 | 102 | public Table getTable() { 103 | return table; 104 | } 105 | 106 | /* package */ void setTable(Table table) { 107 | this.table = table; 108 | } 109 | 110 | /** 111 | * The value set in setValue2Entity(...) 112 | * 113 | * @return -1 or the index of this column. 114 | */ 115 | public int getIndex() { 116 | return index; 117 | } 118 | 119 | public String getColumnName() { 120 | return columnName; 121 | } 122 | 123 | public Object getDefaultValue() { 124 | return defaultValue; 125 | } 126 | 127 | public Field getColumnField() { 128 | return columnField; 129 | } 130 | 131 | public ColumnConverter getColumnConverter() { 132 | return columnConverter; 133 | } 134 | 135 | public ColumnDbType getColumnDbType() { 136 | return columnConverter.getColumnDbType(); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/ColumnUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.text.TextUtils; 19 | import cn.finalteam.sqlitefinal.annotation.Check; 20 | import cn.finalteam.sqlitefinal.annotation.Column; 21 | import cn.finalteam.sqlitefinal.annotation.Finder; 22 | import cn.finalteam.sqlitefinal.annotation.Foreign; 23 | import cn.finalteam.sqlitefinal.annotation.Id; 24 | import cn.finalteam.sqlitefinal.annotation.NotNull; 25 | import cn.finalteam.sqlitefinal.annotation.Transient; 26 | import cn.finalteam.sqlitefinal.annotation.Unique; 27 | import cn.finalteam.sqlitefinal.converter.ColumnConverter; 28 | import cn.finalteam.sqlitefinal.converter.ColumnConverterFactory; 29 | import cn.finalteam.sqlitefinal.sqlite.FinderLazyLoader; 30 | import cn.finalteam.sqlitefinal.sqlite.ForeignLazyLoader; 31 | import java.lang.reflect.Field; 32 | import java.lang.reflect.Method; 33 | import java.lang.reflect.ParameterizedType; 34 | import java.util.HashSet; 35 | import java.util.List; 36 | 37 | public class ColumnUtils { 38 | 39 | private ColumnUtils() { 40 | } 41 | 42 | private static final HashSet DB_PRIMITIVE_TYPES = new HashSet(14); 43 | 44 | static { 45 | DB_PRIMITIVE_TYPES.add(int.class.getName()); 46 | DB_PRIMITIVE_TYPES.add(long.class.getName()); 47 | DB_PRIMITIVE_TYPES.add(short.class.getName()); 48 | DB_PRIMITIVE_TYPES.add(byte.class.getName()); 49 | DB_PRIMITIVE_TYPES.add(float.class.getName()); 50 | DB_PRIMITIVE_TYPES.add(double.class.getName()); 51 | 52 | DB_PRIMITIVE_TYPES.add(Integer.class.getName()); 53 | DB_PRIMITIVE_TYPES.add(Long.class.getName()); 54 | DB_PRIMITIVE_TYPES.add(Short.class.getName()); 55 | DB_PRIMITIVE_TYPES.add(Byte.class.getName()); 56 | DB_PRIMITIVE_TYPES.add(Float.class.getName()); 57 | DB_PRIMITIVE_TYPES.add(Double.class.getName()); 58 | DB_PRIMITIVE_TYPES.add(String.class.getName()); 59 | DB_PRIMITIVE_TYPES.add(byte[].class.getName()); 60 | } 61 | 62 | public static boolean isDbPrimitiveType(Class fieldType) { 63 | return DB_PRIMITIVE_TYPES.contains(fieldType.getName()); 64 | } 65 | 66 | public static Method getColumnGetMethod(Class entityType, Field field) { 67 | String fieldName = field.getName(); 68 | Method getMethod = null; 69 | if (field.getType() == boolean.class) { 70 | getMethod = getBooleanColumnGetMethod(entityType, fieldName); 71 | } 72 | if (getMethod == null) { 73 | String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 74 | try { 75 | getMethod = entityType.getDeclaredMethod(methodName); 76 | } catch (NoSuchMethodException e) { 77 | //Logger.d(methodName + " not exist"); 78 | } 79 | } 80 | 81 | if (getMethod == null && !Object.class.equals(entityType.getSuperclass())) { 82 | return getColumnGetMethod(entityType.getSuperclass(), field); 83 | } 84 | return getMethod; 85 | } 86 | 87 | public static Method getColumnSetMethod(Class entityType, Field field) { 88 | String fieldName = field.getName(); 89 | Method setMethod = null; 90 | if (field.getType() == boolean.class) { 91 | setMethod = getBooleanColumnSetMethod(entityType, field); 92 | } 93 | if (setMethod == null) { 94 | String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 95 | try { 96 | setMethod = entityType.getDeclaredMethod(methodName, field.getType()); 97 | } catch (NoSuchMethodException e) { 98 | //Logger.d(methodName + " not exist"); 99 | } 100 | } 101 | 102 | if (setMethod == null && !Object.class.equals(entityType.getSuperclass())) { 103 | return getColumnSetMethod(entityType.getSuperclass(), field); 104 | } 105 | return setMethod; 106 | } 107 | 108 | 109 | public static String getColumnNameByField(Field field) { 110 | Column column = field.getAnnotation(Column.class); 111 | if (column != null && !TextUtils.isEmpty(column.column())) { 112 | return column.column(); 113 | } 114 | 115 | Id id = field.getAnnotation(Id.class); 116 | if (id != null && !TextUtils.isEmpty(id.column())) { 117 | return id.column(); 118 | } 119 | 120 | Foreign foreign = field.getAnnotation(Foreign.class); 121 | if (foreign != null && !TextUtils.isEmpty(foreign.column())) { 122 | return foreign.column(); 123 | } 124 | 125 | Finder finder = field.getAnnotation(Finder.class); 126 | if (finder != null) { 127 | return field.getName(); 128 | } 129 | 130 | return field.getName(); 131 | } 132 | 133 | public static String getForeignColumnNameByField(Field field) { 134 | 135 | Foreign foreign = field.getAnnotation(Foreign.class); 136 | if (foreign != null) { 137 | return foreign.foreign(); 138 | } 139 | 140 | return field.getName(); 141 | } 142 | 143 | public static String getColumnDefaultValue(Field field) { 144 | Column column = field.getAnnotation(Column.class); 145 | if (column != null && !TextUtils.isEmpty(column.defaultValue())) { 146 | return column.defaultValue(); 147 | } 148 | return null; 149 | } 150 | 151 | public static boolean isTransient(Field field) { 152 | return field.getAnnotation(Transient.class) != null; 153 | } 154 | 155 | public static boolean isForeign(Field field) { 156 | return field.getAnnotation(Foreign.class) != null; 157 | } 158 | 159 | public static boolean isFinder(Field field) { 160 | return field.getAnnotation(Finder.class) != null; 161 | } 162 | 163 | public static boolean isUnique(Field field) { 164 | return field.getAnnotation(Unique.class) != null; 165 | } 166 | 167 | public static boolean isNotNull(Field field) { 168 | return field.getAnnotation(NotNull.class) != null; 169 | } 170 | 171 | /** 172 | * @param field 173 | * @return check.value or null 174 | */ 175 | public static String getCheck(Field field) { 176 | Check check = field.getAnnotation(Check.class); 177 | if (check != null) { 178 | return check.value(); 179 | } else { 180 | return null; 181 | } 182 | } 183 | 184 | @SuppressWarnings("unchecked") 185 | public static Class getForeignEntityType(cn.finalteam.sqlitefinal.table.Foreign foreignColumn) { 186 | Class result = foreignColumn.getColumnField().getType(); 187 | if (result.equals(ForeignLazyLoader.class) || result.equals(List.class)) { 188 | result = (Class) ((ParameterizedType) foreignColumn.getColumnField().getGenericType()).getActualTypeArguments()[0]; 189 | } 190 | return result; 191 | } 192 | 193 | @SuppressWarnings("unchecked") 194 | public static Class getFinderTargetEntityType(cn.finalteam.sqlitefinal.table.Finder finderColumn) { 195 | Class result = finderColumn.getColumnField().getType(); 196 | if (result.equals(FinderLazyLoader.class) || result.equals(List.class)) { 197 | result = (Class) ((ParameterizedType) finderColumn.getColumnField().getGenericType()).getActualTypeArguments()[0]; 198 | } 199 | return result; 200 | } 201 | 202 | @SuppressWarnings("unchecked") 203 | public static Object convert2DbColumnValueIfNeeded(final Object value) { 204 | Object result = value; 205 | if (value != null) { 206 | Class valueType = value.getClass(); 207 | if (!isDbPrimitiveType(valueType)) { 208 | ColumnConverter converter = ColumnConverterFactory.getColumnConverter(valueType); 209 | if (converter != null) { 210 | result = converter.fieldValue2ColumnValue(value); 211 | } else { 212 | result = value; 213 | } 214 | } 215 | } 216 | return result; 217 | } 218 | 219 | private static boolean isStartWithIs(final String fieldName) { 220 | return fieldName != null && fieldName.startsWith("is"); 221 | } 222 | 223 | private static Method getBooleanColumnGetMethod(Class entityType, final String fieldName) { 224 | String methodName = "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 225 | if (isStartWithIs(fieldName)) { 226 | methodName = fieldName; 227 | } 228 | try { 229 | return entityType.getDeclaredMethod(methodName); 230 | } catch (NoSuchMethodException e) { 231 | //Logger.d(methodName + " not exist"); 232 | } 233 | return null; 234 | } 235 | 236 | private static Method getBooleanColumnSetMethod(Class entityType, Field field) { 237 | String fieldName = field.getName(); 238 | String methodName = null; 239 | if (isStartWithIs(field.getName())) { 240 | methodName = "set" + fieldName.substring(2, 3).toUpperCase() + fieldName.substring(3); 241 | } else { 242 | methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); 243 | } 244 | try { 245 | return entityType.getDeclaredMethod(methodName, field.getType()); 246 | } catch (NoSuchMethodException e) { 247 | //Logger.d(methodName + " not exist"); 248 | } 249 | return null; 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/DbModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.text.TextUtils; 19 | import java.util.Date; 20 | import java.util.HashMap; 21 | 22 | public class DbModel { 23 | 24 | /** 25 | * key: columnName 26 | * value: valueStr 27 | */ 28 | private HashMap dataMap = new HashMap(); 29 | 30 | public String getString(String columnName) { 31 | return dataMap.get(columnName); 32 | } 33 | 34 | public int getInt(String columnName) { 35 | return Integer.valueOf(dataMap.get(columnName)); 36 | } 37 | 38 | public boolean getBoolean(String columnName) { 39 | String value = dataMap.get(columnName); 40 | if (value != null) { 41 | return value.length() == 1 ? "1".equals(value) : Boolean.valueOf(value); 42 | } 43 | return false; 44 | } 45 | 46 | public double getDouble(String columnName) { 47 | return Double.valueOf(dataMap.get(columnName)); 48 | } 49 | 50 | public float getFloat(String columnName) { 51 | return Float.valueOf(dataMap.get(columnName)); 52 | } 53 | 54 | public long getLong(String columnName) { 55 | return Long.valueOf(dataMap.get(columnName)); 56 | } 57 | 58 | public Date getDate(String columnName) { 59 | long date = Long.valueOf(dataMap.get(columnName)); 60 | return new Date(date); 61 | } 62 | 63 | public java.sql.Date getSqlDate(String columnName) { 64 | long date = Long.valueOf(dataMap.get(columnName)); 65 | return new java.sql.Date(date); 66 | } 67 | 68 | public void add(String columnName, String valueStr) { 69 | dataMap.put(columnName, valueStr); 70 | } 71 | 72 | /** 73 | * @return key: columnName 74 | */ 75 | public HashMap getDataMap() { 76 | return dataMap; 77 | } 78 | 79 | /** 80 | * @param columnName 81 | * @return 82 | */ 83 | public boolean isEmpty(String columnName) { 84 | return TextUtils.isEmpty(dataMap.get(columnName)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/Finder.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.table; 2 | 3 | import android.database.Cursor; 4 | import cn.finalteam.sqlitefinal.exception.DbException; 5 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 6 | import cn.finalteam.sqlitefinal.sqlite.FinderLazyLoader; 7 | import java.lang.reflect.Field; 8 | import java.util.List; 9 | 10 | /** 11 | * Author: wyouflf 12 | * Date: 13-9-10 13 | * Time: 下午7:43 14 | */ 15 | public class Finder extends Column { 16 | 17 | private final String valueColumnName; 18 | private final String targetColumnName; 19 | 20 | /* package */ Finder(Class entityType, Field field) { 21 | super(entityType, field); 22 | 23 | cn.finalteam.sqlitefinal.annotation.Finder finder = 24 | field.getAnnotation(cn.finalteam.sqlitefinal.annotation.Finder.class); 25 | this.valueColumnName = finder.valueColumn(); 26 | this.targetColumnName = finder.targetColumn(); 27 | } 28 | 29 | public Class getTargetEntityType() { 30 | return ColumnUtils.getFinderTargetEntityType(this); 31 | } 32 | 33 | public String getTargetColumnName() { 34 | return targetColumnName; 35 | } 36 | 37 | @Override 38 | public void setValue2Entity(Object entity, Cursor cursor, int index) { 39 | Object value = null; 40 | Class columnType = columnField.getType(); 41 | Object finderValue = TableUtils.getColumnOrId(entity.getClass(), this.valueColumnName).getColumnValue(entity); 42 | if (columnType.equals(FinderLazyLoader.class)) { 43 | value = new FinderLazyLoader(this, finderValue); 44 | } else if (columnType.equals(List.class)) { 45 | try { 46 | value = new FinderLazyLoader(this, finderValue).getAllFromDb(); 47 | } catch (DbException e) { 48 | //Logger.e(e.getMessage(), e); 49 | } 50 | } else { 51 | try { 52 | value = new FinderLazyLoader(this, finderValue).getFirstFromDb(); 53 | } catch (DbException e) { 54 | //Logger.e(e.getMessage(), e); 55 | } 56 | } 57 | 58 | if (setMethod != null) { 59 | try { 60 | setMethod.invoke(entity, value); 61 | } catch (Throwable e) { 62 | //Logger.e(e.getMessage(), e); 63 | } 64 | } else { 65 | try { 66 | this.columnField.setAccessible(true); 67 | this.columnField.set(entity, value); 68 | } catch (Throwable e) { 69 | //Logger.e(e.getMessage(), e); 70 | } 71 | } 72 | } 73 | 74 | @Override 75 | public Object getColumnValue(Object entity) { 76 | return null; 77 | } 78 | 79 | @Override 80 | public Object getDefaultValue() { 81 | return null; 82 | } 83 | 84 | @Override 85 | public ColumnDbType getColumnDbType() { 86 | return ColumnDbType.TEXT; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/Foreign.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.database.Cursor; 19 | import cn.finalteam.sqlitefinal.converter.ColumnConverter; 20 | import cn.finalteam.sqlitefinal.converter.ColumnConverterFactory; 21 | import cn.finalteam.sqlitefinal.exception.DbException; 22 | import cn.finalteam.sqlitefinal.sqlite.ColumnDbType; 23 | import cn.finalteam.sqlitefinal.sqlite.ForeignLazyLoader; 24 | import java.lang.reflect.Field; 25 | import java.util.List; 26 | 27 | public class Foreign extends Column { 28 | 29 | private final String foreignColumnName; 30 | private final ColumnConverter foreignColumnConverter; 31 | 32 | /* package */ Foreign(Class entityType, Field field) { 33 | super(entityType, field); 34 | 35 | foreignColumnName = ColumnUtils.getForeignColumnNameByField(field); 36 | Class foreignColumnType = 37 | TableUtils.getColumnOrId(getForeignEntityType(), foreignColumnName).columnField.getType(); 38 | foreignColumnConverter = ColumnConverterFactory.getColumnConverter(foreignColumnType); 39 | } 40 | 41 | public String getForeignColumnName() { 42 | return foreignColumnName; 43 | } 44 | 45 | public Class getForeignEntityType() { 46 | return ColumnUtils.getForeignEntityType(this); 47 | } 48 | 49 | @SuppressWarnings("unchecked") 50 | @Override 51 | public void setValue2Entity(Object entity, Cursor cursor, int index) { 52 | Object fieldValue = foreignColumnConverter.getFieldValue(cursor, index); 53 | if (fieldValue == null) return; 54 | 55 | Object value = null; 56 | Class columnType = columnField.getType(); 57 | if (columnType.equals(ForeignLazyLoader.class)) { 58 | value = new ForeignLazyLoader(this, fieldValue); 59 | } else if (columnType.equals(List.class)) { 60 | try { 61 | value = new ForeignLazyLoader(this, fieldValue).getAllFromDb(); 62 | } catch (DbException e) { 63 | //Logger.e(e.getMessage(), e); 64 | } 65 | } else { 66 | try { 67 | value = new ForeignLazyLoader(this, fieldValue).getFirstFromDb(); 68 | } catch (DbException e) { 69 | //Logger.e(e.getMessage(), e); 70 | } 71 | } 72 | 73 | if (setMethod != null) { 74 | try { 75 | setMethod.invoke(entity, value); 76 | } catch (Throwable e) { 77 | //Logger.e(e.getMessage(), e); 78 | } 79 | } else { 80 | try { 81 | this.columnField.setAccessible(true); 82 | this.columnField.set(entity, value); 83 | } catch (Throwable e) { 84 | //Logger.e(e.getMessage(), e); 85 | } 86 | } 87 | } 88 | 89 | @SuppressWarnings("unchecked") 90 | @Override 91 | public Object getColumnValue(Object entity) { 92 | Object fieldValue = getFieldValue(entity); 93 | Object columnValue = null; 94 | 95 | if (fieldValue != null) { 96 | Class columnType = columnField.getType(); 97 | if (columnType.equals(ForeignLazyLoader.class)) { 98 | columnValue = ((ForeignLazyLoader) fieldValue).getColumnValue(); 99 | } else if (columnType.equals(List.class)) { 100 | try { 101 | List foreignEntities = (List) fieldValue; 102 | if (foreignEntities.size() > 0) { 103 | 104 | Class foreignEntityType = ColumnUtils.getForeignEntityType(this); 105 | Column column = TableUtils.getColumnOrId(foreignEntityType, foreignColumnName); 106 | columnValue = column.getColumnValue(foreignEntities.get(0)); 107 | 108 | // 仅自动关联外键 109 | Table table = this.getTable(); 110 | if (table != null && column instanceof Id) { 111 | for (Object foreignObj : foreignEntities) { 112 | Object idValue = column.getColumnValue(foreignObj); 113 | if (idValue == null) { 114 | table.db.saveOrUpdate(foreignObj); 115 | } 116 | } 117 | } 118 | 119 | columnValue = column.getColumnValue(foreignEntities.get(0)); 120 | } 121 | } catch (Throwable e) { 122 | //Logger.e(e.getMessage(), e); 123 | } 124 | } else { 125 | try { 126 | Column column = TableUtils.getColumnOrId(columnType, foreignColumnName); 127 | columnValue = column.getColumnValue(fieldValue); 128 | 129 | Table table = this.getTable(); 130 | if (table != null && columnValue == null && column instanceof Id) { 131 | table.db.saveOrUpdate(fieldValue); 132 | } 133 | 134 | columnValue = column.getColumnValue(fieldValue); 135 | } catch (Throwable e) { 136 | //Logger.e(e.getMessage(), e); 137 | } 138 | } 139 | } 140 | 141 | return columnValue; 142 | } 143 | 144 | @Override 145 | public ColumnDbType getColumnDbType() { 146 | return foreignColumnConverter.getColumnDbType(); 147 | } 148 | 149 | /** 150 | * It always return null. 151 | * 152 | * @return null 153 | */ 154 | @Override 155 | public Object getDefaultValue() { 156 | return null; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/Id.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import cn.finalteam.sqlitefinal.annotation.NoAutoIncrement; 19 | import java.lang.reflect.Field; 20 | import java.util.HashSet; 21 | 22 | public class Id extends Column { 23 | 24 | private String columnFieldClassName; 25 | private boolean isAutoIncrementChecked = false; 26 | private boolean isAutoIncrement = false; 27 | 28 | /* package */ Id(Class entityType, Field field) { 29 | super(entityType, field); 30 | columnFieldClassName = columnField.getType().getName(); 31 | } 32 | 33 | public boolean isAutoIncrement() { 34 | if (!isAutoIncrementChecked) { 35 | isAutoIncrementChecked = true; 36 | isAutoIncrement = columnField.getAnnotation(NoAutoIncrement.class) == null 37 | && AUTO_INCREMENT_TYPES.contains(columnFieldClassName); 38 | } 39 | return isAutoIncrement; 40 | } 41 | 42 | public void setAutoIncrementId(Object entity, long value) { 43 | Object idValue = value; 44 | if (INTEGER_TYPES.contains(columnFieldClassName)) { 45 | idValue = (int) value; 46 | } 47 | 48 | if (setMethod != null) { 49 | try { 50 | setMethod.invoke(entity, idValue); 51 | } catch (Throwable e) { 52 | //Logger.e(e.getMessage(), e); 53 | } 54 | } else { 55 | try { 56 | this.columnField.setAccessible(true); 57 | this.columnField.set(entity, idValue); 58 | } catch (Throwable e) { 59 | //Logger.e(e.getMessage(), e); 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public Object getColumnValue(Object entity) { 66 | Object idValue = super.getColumnValue(entity); 67 | if (idValue != null) { 68 | if (this.isAutoIncrement() && (idValue.equals(0) || idValue.equals(0L))) { 69 | return null; 70 | } else { 71 | return idValue; 72 | } 73 | } 74 | return null; 75 | } 76 | 77 | private static final HashSet INTEGER_TYPES = new HashSet(2); 78 | private static final HashSet AUTO_INCREMENT_TYPES = new HashSet(4); 79 | 80 | static { 81 | INTEGER_TYPES.add(int.class.getName()); 82 | INTEGER_TYPES.add(Integer.class.getName()); 83 | 84 | AUTO_INCREMENT_TYPES.addAll(INTEGER_TYPES); 85 | AUTO_INCREMENT_TYPES.add(long.class.getName()); 86 | AUTO_INCREMENT_TYPES.add(Long.class.getName()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/KeyValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | public class KeyValue { 19 | public final String key; 20 | public final Object value; 21 | 22 | public KeyValue(String key, Object value) { 23 | this.key = key; 24 | this.value = value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/Table.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.text.TextUtils; 19 | import cn.finalteam.sqlitefinal.DbHelper; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | public class Table { 24 | 25 | public final DbHelper db; 26 | public final String tableName; 27 | public final Id id; 28 | 29 | /** 30 | * key: columnName 31 | */ 32 | public final HashMap columnMap; 33 | 34 | /** 35 | * key: columnName 36 | */ 37 | public final HashMap finderMap; 38 | 39 | /** 40 | * key: dbName#className 41 | */ 42 | private static final HashMap tableMap = new HashMap(); 43 | 44 | private Table(DbHelper db, Class entityType) { 45 | this.db = db; 46 | this.tableName = TableUtils.getTableName(entityType); 47 | this.id = TableUtils.getId(entityType); 48 | this.columnMap = TableUtils.getColumnMap(entityType); 49 | 50 | finderMap = new HashMap(); 51 | for (Column column : columnMap.values()) { 52 | column.setTable(this); 53 | if (column instanceof Finder) { 54 | finderMap.put(column.getColumnName(), (Finder) column); 55 | } 56 | } 57 | } 58 | 59 | public static synchronized Table get(DbHelper db, Class entityType) { 60 | String tableKey = db.getDaoConfig().getDbName() + "#" + entityType.getName(); 61 | Table table = tableMap.get(tableKey); 62 | if (table == null) { 63 | table = new Table(db, entityType); 64 | tableMap.put(tableKey, table); 65 | } 66 | 67 | return table; 68 | } 69 | 70 | public static synchronized void remove(DbHelper db, Class entityType) { 71 | String tableKey = db.getDaoConfig().getDbName() + "#" + entityType.getName(); 72 | tableMap.remove(tableKey); 73 | } 74 | 75 | public static synchronized void remove(DbHelper db, String tableName) { 76 | if (tableMap.size() > 0) { 77 | String key = null; 78 | for (Map.Entry entry : tableMap.entrySet()) { 79 | Table table = entry.getValue(); 80 | if (table != null && table.tableName.equals(tableName)) { 81 | key = entry.getKey(); 82 | if (key.startsWith(db.getDaoConfig().getDbName() + "#")) { 83 | break; 84 | } 85 | } 86 | } 87 | if (TextUtils.isEmpty(key)) { 88 | tableMap.remove(key); 89 | } 90 | } 91 | } 92 | 93 | private boolean checkedDatabase; 94 | 95 | public boolean isCheckedDatabase() { 96 | return checkedDatabase; 97 | } 98 | 99 | public void setCheckedDatabase(boolean checkedDatabase) { 100 | this.checkedDatabase = checkedDatabase; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/table/TableUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@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 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package cn.finalteam.sqlitefinal.table; 17 | 18 | import android.text.TextUtils; 19 | import cn.finalteam.sqlitefinal.annotation.Id; 20 | import cn.finalteam.sqlitefinal.annotation.Table; 21 | import cn.finalteam.sqlitefinal.converter.ColumnConverterFactory; 22 | import java.lang.reflect.Field; 23 | import java.lang.reflect.Modifier; 24 | import java.util.HashMap; 25 | import java.util.concurrent.ConcurrentHashMap; 26 | 27 | public class TableUtils { 28 | 29 | private TableUtils() { 30 | } 31 | 32 | public static String getTableName(Class entityType) { 33 | Table table = entityType.getAnnotation(Table.class); 34 | if (table == null || TextUtils.isEmpty(table.name())) { 35 | return entityType.getName().replace('.', '_'); 36 | } 37 | return table.name(); 38 | } 39 | 40 | public static String getExecAfterTableCreated(Class entityType) { 41 | Table table = entityType.getAnnotation(Table.class); 42 | if (table != null) { 43 | return table.execAfterTableCreated(); 44 | } 45 | return null; 46 | } 47 | 48 | /** 49 | * key: entityType.name 50 | */ 51 | private static ConcurrentHashMap> entityColumnsMap = new ConcurrentHashMap>(); 52 | 53 | /* package */ 54 | static synchronized HashMap getColumnMap(Class entityType) { 55 | 56 | if (entityColumnsMap.containsKey(entityType.getName())) { 57 | return entityColumnsMap.get(entityType.getName()); 58 | } 59 | 60 | HashMap columnMap = new HashMap(); 61 | String primaryKeyFieldName = getPrimaryKeyFieldName(entityType); 62 | addColumns2Map(entityType, primaryKeyFieldName, columnMap); 63 | entityColumnsMap.put(entityType.getName(), columnMap); 64 | 65 | return columnMap; 66 | } 67 | 68 | private static void addColumns2Map(Class entityType, String primaryKeyFieldName, HashMap columnMap) { 69 | if (Object.class.equals(entityType)) return; 70 | try { 71 | Field[] fields = entityType.getDeclaredFields(); 72 | for (Field field : fields) { 73 | if (ColumnUtils.isTransient(field) || Modifier.isStatic(field.getModifiers())) { 74 | continue; 75 | } 76 | if (ColumnConverterFactory.isSupportColumnConverter(field.getType())) { 77 | if (!field.getName().equals(primaryKeyFieldName)) { 78 | Column column = new Column(entityType, field); 79 | if (!columnMap.containsKey(column.getColumnName())) { 80 | columnMap.put(column.getColumnName(), column); 81 | } 82 | } 83 | } else if (ColumnUtils.isForeign(field)) { 84 | Foreign column = new Foreign(entityType, field); 85 | if (!columnMap.containsKey(column.getColumnName())) { 86 | columnMap.put(column.getColumnName(), column); 87 | } 88 | } else if (ColumnUtils.isFinder(field)) { 89 | Finder column = new Finder(entityType, field); 90 | if (!columnMap.containsKey(column.getColumnName())) { 91 | columnMap.put(column.getColumnName(), column); 92 | } 93 | } 94 | } 95 | 96 | if (!Object.class.equals(entityType.getSuperclass())) { 97 | addColumns2Map(entityType.getSuperclass(), primaryKeyFieldName, columnMap); 98 | } 99 | } catch (Throwable e) { 100 | //Logger.e(e.getMessage(), e); 101 | } 102 | } 103 | 104 | /* package */ 105 | static Column getColumnOrId(Class entityType, String columnName) { 106 | if (getPrimaryKeyColumnName(entityType).equals(columnName)) { 107 | return getId(entityType); 108 | } 109 | return getColumnMap(entityType).get(columnName); 110 | } 111 | 112 | /** 113 | * key: entityType.name 114 | */ 115 | private static ConcurrentHashMap entityIdMap = new ConcurrentHashMap(); 116 | 117 | /* package */ 118 | static synchronized cn.finalteam.sqlitefinal.table.Id getId(Class entityType) { 119 | if (Object.class.equals(entityType)) { 120 | throw new RuntimeException("field 'id' not found"); 121 | } 122 | 123 | if (entityIdMap.containsKey(entityType.getName())) { 124 | return entityIdMap.get(entityType.getName()); 125 | } 126 | 127 | Field primaryKeyField = null; 128 | Field[] fields = entityType.getDeclaredFields(); 129 | if (fields != null) { 130 | 131 | for (Field field : fields) { 132 | if (field.getAnnotation(Id.class) != null) { 133 | primaryKeyField = field; 134 | break; 135 | } 136 | } 137 | 138 | if (primaryKeyField == null) { 139 | for (Field field : fields) { 140 | if ("id".equals(field.getName()) || "_id".equals(field.getName())) { 141 | primaryKeyField = field; 142 | break; 143 | } 144 | } 145 | } 146 | } 147 | 148 | if (primaryKeyField == null) { 149 | return getId(entityType.getSuperclass()); 150 | } 151 | 152 | cn.finalteam.sqlitefinal.table.Id id = new cn.finalteam.sqlitefinal.table.Id(entityType, primaryKeyField); 153 | entityIdMap.put(entityType.getName(), id); 154 | return id; 155 | } 156 | 157 | private static String getPrimaryKeyFieldName(Class entityType) { 158 | cn.finalteam.sqlitefinal.table.Id id = getId(entityType); 159 | return id == null ? null : id.getColumnField().getName(); 160 | } 161 | 162 | private static String getPrimaryKeyColumnName(Class entityType) { 163 | cn.finalteam.sqlitefinal.table.Id id = getId(entityType); 164 | return id == null ? null : id.getColumnName(); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /sqlitefinal/src/main/java/cn/finalteam/sqlitefinal/utils/IOUtils.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal.utils; 2 | 3 | import android.database.Cursor; 4 | import java.io.Closeable; 5 | 6 | /** 7 | * Desction:IO工具类 8 | * Author:pengjianbo 9 | * Date:15/7/3 上午11:04 10 | */ 11 | public class IOUtils { 12 | 13 | private IOUtils() { 14 | } 15 | 16 | public static void closeQuietly(Closeable closeable) { 17 | if (closeable != null) { 18 | try { 19 | closeable.close(); 20 | } catch (Throwable e) { 21 | } 22 | } 23 | } 24 | 25 | public static void closeQuietly(Cursor cursor) { 26 | if (cursor != null) { 27 | try { 28 | cursor.close(); 29 | } catch (Throwable e) { 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sqlitefinal/src/test/java/cn/finalteam/sqlitefinal/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.finalteam.sqlitefinal; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } --------------------------------------------------------------------------------