├── .gitignore ├── README.md ├── app ├── build.gradle ├── objectbox-models │ └── default.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── ds │ │ └── dbtests │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── ds │ │ │ └── dbtests │ │ │ ├── App.kt │ │ │ ├── Benchmark.kt │ │ │ ├── ChartActivity.kt │ │ │ ├── ChartData.kt │ │ │ ├── Extensions.kt │ │ │ ├── MainActivity.kt │ │ │ ├── Test.kt │ │ │ ├── TestResult.kt │ │ │ └── db │ │ │ ├── Order.kt │ │ │ ├── User.kt │ │ │ ├── dbflow │ │ │ ├── DBFlowDatabase.java │ │ │ ├── OrderDBFlow.java │ │ │ └── UserDBFlow.java │ │ │ ├── firebase │ │ │ ├── OrderFB.java │ │ │ └── UserFB.java │ │ │ ├── greendao │ │ │ ├── OrderGreenDao.java │ │ │ └── UserGreenDao.java │ │ │ ├── objectbox │ │ │ ├── OrderBox.java │ │ │ └── UserBox.java │ │ │ ├── orma │ │ │ ├── OrderOrma.java │ │ │ └── UserOrma.java │ │ │ ├── ormlite │ │ │ ├── OrderOrmLite.kt │ │ │ ├── OrmLiteDB.kt │ │ │ └── UserOrmLite.kt │ │ │ ├── realm │ │ │ ├── OrderRealm.kt │ │ │ └── UserRealm.kt │ │ │ ├── requery │ │ │ ├── OrderRequery.java │ │ │ ├── RequeryTest.kt │ │ │ └── UserRequery.java │ │ │ ├── room │ │ │ ├── AppDatabase.java │ │ │ ├── Converters.java │ │ │ ├── OrderDao.java │ │ │ ├── OrderRoom.java │ │ │ ├── UserDao.java │ │ │ └── UserRoom.java │ │ │ └── snappydb │ │ │ ├── OrderSnappy.kt │ │ │ └── UserSnappy.kt │ └── res │ │ ├── layout │ │ ├── activity_chart.xml │ │ └── activity_main.xml │ │ ├── menu │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── ds │ └── dbtests │ └── ExampleUnitTest.java ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pics └── screenshot.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | *.properties 3 | /.idea 4 | build 5 | *.iml 6 | google-services.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### ORM Benchmarks 2 | - GreenDAO https://github.com/greenrobot/greenDAO 3 | - ObjectBox https://github.com/greenrobot/ObjectBox 4 | - Orma https://github.com/gfx/Android-Orma 5 | - DBFlow https://github.com/Raizlabs/DBFlow 6 | - Realm https://github.com/realm/realm-java 7 | - ORMLite https://github.com/j256/ormlite-android 8 | - Requery https://github.com/requery/requery 9 | - SnappyDB https://github.com/nhachicha/SnappyDB 10 | - Room https://developer.android.com/topic/libraries/architecture/room.html 11 | - Firebase (you need to setup json config manually) 12 | 13 | ![](pics/screenshot.png) 14 | 15 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'org.greenrobot.greendao' 2 | apply plugin: 'io.objectbox' 3 | apply plugin: 'com.android.application' 4 | apply plugin: 'com.jakewharton.hugo' 5 | apply plugin: 'kotlin-android' 6 | apply plugin: 'kotlin-kapt' 7 | apply plugin: 'realm-android' 8 | 9 | android { 10 | compileSdkVersion 27 11 | buildToolsVersion '27.0.3' 12 | 13 | defaultConfig { 14 | applicationId "ds.dbtests" 15 | minSdkVersion 21 16 | targetSdkVersion 27 17 | versionCode 1 18 | versionName "1.0" 19 | multiDexEnabled true 20 | javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true 21 | 22 | } 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_7 32 | targetCompatibility JavaVersion.VERSION_1_7 33 | } 34 | 35 | dexOptions { 36 | //javaMaxHeapSize "4g" 37 | } 38 | 39 | packagingOptions { 40 | exclude 'META-INF/LICENSE' 41 | exclude 'META-INF/NOTICE' 42 | exclude 'META-INF/services/javax.annotation.processing.Processor' 43 | } 44 | 45 | } 46 | 47 | greendao { 48 | schemaVersion 9 49 | } 50 | 51 | dependencies { 52 | def dbflow_version = "4.2.4" 53 | def orma_version = "4.2.5" 54 | 55 | compile fileTree(dir: 'libs', include: ['*.jar']) 56 | compile 'com.android.support:appcompat-v7:27.0.2' 57 | 58 | // orms 59 | compile 'com.j256.ormlite:ormlite-android:5.0' 60 | compile 'org.greenrobot:greendao:3.2.2' 61 | compile "com.github.gfx.android.orma:orma:${orma_version}" 62 | kapt "com.github.gfx.android.orma:orma-processor:${orma_version}" 63 | kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}" 64 | compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}" 65 | compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}" 66 | //compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${dbflow_version}" 67 | compile 'com.snappydb:snappydb-lib:0.5.2' 68 | compile 'io.requery:requery:1.4.1' 69 | compile 'io.requery:requery-android:1.4.1' // for android 70 | kapt 'io.requery:requery-processor:1.4.1' // prefer an APT plugin 71 | compile 'io.requery:sqlite-android:3.21.0' 72 | compile 'com.google.firebase:firebase-core:11.8.0' 73 | compile 'com.google.firebase:firebase-database:11.8.0' 74 | compile 'io.objectbox:objectbox-android:0.9.9' 75 | //compile 'io.objectbox:objectbox-daocompat:1.1.0' 76 | compile "android.arch.persistence.room:runtime:1.0.0" 77 | kapt "android.arch.persistence.room:compiler:1.0.0" 78 | 79 | compile 'com.esotericsoftware.kryo:kryo:2.24.0' 80 | compile 'com.jakewharton:kotterknife:0.1.0-SNAPSHOT' 81 | compile 'io.reactivex.rxjava2:rxjava:2.1.6' // https://github.com/ReactiveX/RxJava 82 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 83 | compile 'io.reactivex.rxjava2:rxkotlin:2.0.0' 84 | 85 | //compile 'de.ruedigermoeller:fst:2.48' 86 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" 87 | compile 'com.facebook.stetho:stetho:1.5.0' 88 | compile 'com.uphyca:stetho_realm:2.0.0' 89 | compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' //v3.0.2 90 | 91 | } 92 | 93 | apply plugin: 'com.google.gms.google-services' 94 | 95 | -------------------------------------------------------------------------------- /app/objectbox-models/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", 3 | "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", 4 | "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", 5 | "entities": [ 6 | { 7 | "id": "1:3052155692983338597", 8 | "lastPropertyId": "9:5680599390499331371", 9 | "name": "OrderBox", 10 | "properties": [ 11 | { 12 | "id": "1:8729756949400444000", 13 | "name": "id" 14 | }, 15 | { 16 | "id": "2:6335063551321622490", 17 | "name": "title" 18 | }, 19 | { 20 | "id": "3:6387580835613096947", 21 | "name": "price" 22 | }, 23 | { 24 | "id": "4:2005818079908249803", 25 | "name": "count" 26 | }, 27 | { 28 | "id": "5:5566431553947545352", 29 | "name": "created" 30 | }, 31 | { 32 | "id": "6:8659284856683359185", 33 | "name": "expiration" 34 | }, 35 | { 36 | "id": "7:2674424989060710381", 37 | "name": "description" 38 | }, 39 | { 40 | "id": "9:5680599390499331371", 41 | "indexId": "1:3420884453405280558", 42 | "name": "userId" 43 | } 44 | ] 45 | }, 46 | { 47 | "id": "2:7259040085820859491", 48 | "lastPropertyId": "11:7852989507892736129", 49 | "name": "UserBox", 50 | "properties": [ 51 | { 52 | "id": "1:3959393091527181675", 53 | "name": "id" 54 | }, 55 | { 56 | "id": "2:5505069154706475581", 57 | "name": "age" 58 | }, 59 | { 60 | "id": "3:7123704602774178556", 61 | "name": "height" 62 | }, 63 | { 64 | "id": "4:9190189809884933099", 65 | "name": "name" 66 | }, 67 | { 68 | "id": "5:9037366412318974785", 69 | "name": "login" 70 | }, 71 | { 72 | "id": "6:7023010357429710186", 73 | "name": "password" 74 | }, 75 | { 76 | "id": "7:4117456730004278892", 77 | "name": "sex" 78 | }, 79 | { 80 | "id": "8:113708315554172314", 81 | "name": "description" 82 | }, 83 | { 84 | "id": "9:2596839985584304932", 85 | "name": "phone" 86 | } 87 | ] 88 | } 89 | ], 90 | "lastEntityId": "2:7259040085820859491", 91 | "lastIndexId": "1:3420884453405280558", 92 | "lastSequenceId": "0:0", 93 | "modelVersion": 2, 94 | "retiredEntityUids": [], 95 | "retiredIndexUids": [], 96 | "retiredPropertyUids": [ 97 | 4659821816084033903, 98 | 4667045475012416812, 99 | 7852989507892736129 100 | ], 101 | "version": 1 102 | } -------------------------------------------------------------------------------- /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 C:\dev\android-sdk-windows/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/ds/dbtests/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | 11 | public ApplicationTest() { 12 | super(Application.class); 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/App.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | import android.app.Application 4 | import com.facebook.stetho.Stetho 5 | import com.raizlabs.android.dbflow.config.FlowConfig 6 | import com.raizlabs.android.dbflow.config.FlowLog 7 | import com.raizlabs.android.dbflow.config.FlowManager 8 | import com.uphyca.stetho_realm.RealmInspectorModulesProvider 9 | 10 | class App : Application() { 11 | override fun onCreate() { 12 | super.onCreate() 13 | instance = this 14 | Stetho.initializeWithDefaults(this) 15 | Stetho.initialize(Stetho.newInitializerBuilder(this) 16 | .enableDumpapp(Stetho.defaultDumperPluginsProvider(this)) 17 | .enableWebKitInspector(RealmInspectorModulesProvider.builder(this).build()) 18 | .build()) 19 | 20 | /*val config = RealmConfiguration.Builder(this) 21 | .name("default") 22 | .schemaVersion(1) 23 | .deleteRealmIfMigrationNeeded() 24 | .build() 25 | 26 | Realm.setDefaultConfiguration(config)*/ 27 | 28 | // init dbflow 29 | val flowConfig = FlowConfig.Builder(this).build() 30 | FlowManager.init(flowConfig) 31 | FlowLog.setMinimumLoggingLevel(FlowLog.Level.E); 32 | } 33 | 34 | companion object { 35 | lateinit var instance: App 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/Benchmark.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | // todo 4 | interface Benchmark { 5 | fun init() 6 | fun writeTest() 7 | fun readTest() 8 | fun clean() 9 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/ChartActivity.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | import android.os.Bundle 4 | import android.support.v4.content.ContextCompat 5 | import android.support.v7.app.AppCompatActivity 6 | import android.util.Log 7 | import com.github.mikephil.charting.charts.BarChart 8 | import com.github.mikephil.charting.components.Legend 9 | import com.github.mikephil.charting.components.XAxis 10 | import com.github.mikephil.charting.data.BarData 11 | import com.github.mikephil.charting.data.BarDataSet 12 | import com.github.mikephil.charting.data.BarEntry 13 | import com.github.mikephil.charting.data.Entry 14 | import com.github.mikephil.charting.highlight.Highlight 15 | import com.github.mikephil.charting.interfaces.datasets.IBarDataSet 16 | import com.github.mikephil.charting.listener.OnChartValueSelectedListener 17 | import java.util.* 18 | 19 | class ChartActivity : AppCompatActivity(), OnChartValueSelectedListener { 20 | 21 | private lateinit var chart: BarChart 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.activity_chart) 26 | chart = findViewById(R.id.chart) as BarChart 27 | 28 | chart.setOnChartValueSelectedListener(this) 29 | 30 | chart.setDescription("") 31 | 32 | // scaling can now only be done on x- and y-axis separately 33 | chart.setPinchZoom(false) 34 | 35 | chart.setDrawBarShadow(false) 36 | 37 | chart.setDrawGridBackground(false) 38 | 39 | val l = chart.legend 40 | l.position = Legend.LegendPosition.ABOVE_CHART_CENTER 41 | 42 | val leftAxis = chart.axisLeft 43 | //leftAxis.valueFormatter = LargeValueFormatter() 44 | leftAxis.setDrawGridLines(false) 45 | 46 | val xAxis = chart.xAxis 47 | xAxis.position = XAxis.XAxisPosition.TOP_INSIDE 48 | 49 | chart.axisRight.isEnabled = false 50 | 51 | setData() 52 | } 53 | 54 | private fun setData() { 55 | 56 | val tests = ChartData.results 57 | if (tests.size == 0) 58 | return 59 | 60 | tests.sortByDescending { it.readValue } 61 | 62 | val xVals = ArrayList() 63 | val writeVals = ArrayList() 64 | val readVals = ArrayList() 65 | 66 | for ((index, t) in tests.withIndex()) { 67 | writeVals.add(BarEntry(t.writeValue.toFloat(), index, t.writeMessage)) 68 | readVals.add(BarEntry(t.readValue.toFloat(), index, t.readMessage)) 69 | xVals.add(t.title!!) 70 | } 71 | 72 | val writeSet = BarDataSet(writeVals, "Write") 73 | writeSet.color = ContextCompat.getColor(this, R.color.red) 74 | val readSet = BarDataSet(readVals, "Read") 75 | readSet.color = ContextCompat.getColor(this, R.color.green) 76 | 77 | val dataSets = ArrayList() 78 | dataSets.add(readSet) 79 | dataSets.add(writeSet) 80 | 81 | val data = BarData(xVals, dataSets) 82 | data.setValueTextSize(10f) 83 | chart.data = data 84 | chart.animateY(1000) 85 | chart.invalidate() 86 | } 87 | 88 | override fun onValueSelected(e: Entry, dataSetIndex: Int, h: Highlight) { 89 | Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + dataSetIndex) 90 | } 91 | 92 | override fun onNothingSelected() { 93 | Log.i("Activity", "Nothing selected.") 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/ChartData.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | object ChartData { 4 | val results: MutableList = arrayListOf() 5 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/Extensions.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | import android.content.Context 4 | import android.os.Looper 5 | import android.text.TextUtils 6 | import android.util.TypedValue 7 | 8 | fun isMainThread(): Boolean = (Looper.myLooper() == Looper.getMainLooper()) 9 | 10 | operator fun CharSequence.plus(operand: CharSequence): CharSequence = TextUtils.concat(this, operand) 11 | 12 | fun Context.dp(i: Int): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i.toFloat(), resources.displayMetrics) -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | import android.arch.persistence.room.Room 4 | import android.arch.persistence.room.RoomDatabase 5 | import android.content.Intent 6 | import android.os.Bundle 7 | import android.support.v7.app.AppCompatActivity 8 | import android.util.Log 9 | import android.view.Menu 10 | import android.view.MenuItem 11 | import android.widget.TextView 12 | import com.github.gfx.android.orma.AccessThreadConstraint 13 | import com.github.gfx.android.orma.SingleAssociation 14 | import com.google.firebase.database.DataSnapshot 15 | import com.google.firebase.database.DatabaseError 16 | import com.google.firebase.database.FirebaseDatabase 17 | import com.google.firebase.database.ValueEventListener 18 | import com.j256.ormlite.table.TableUtils 19 | import com.raizlabs.android.dbflow.config.FlowManager 20 | import com.raizlabs.android.dbflow.sql.language.Delete 21 | import com.raizlabs.android.dbflow.sql.language.Select 22 | import com.snappydb.DB 23 | import com.snappydb.DBFactory 24 | import ds.dbtests.db.User 25 | import ds.dbtests.db.dbflow.DBFlowDatabase 26 | import ds.dbtests.db.dbflow.OrderDBFlow 27 | import ds.dbtests.db.dbflow.UserDBFlow 28 | import ds.dbtests.db.firebase.OrderFB 29 | import ds.dbtests.db.firebase.UserFB 30 | import ds.dbtests.db.greendao.DaoMaster 31 | import ds.dbtests.db.greendao.DaoSession 32 | import ds.dbtests.db.greendao.OrderGreenDao 33 | import ds.dbtests.db.greendao.UserGreenDao 34 | import ds.dbtests.db.objectbox.MyObjectBox 35 | import ds.dbtests.db.objectbox.OrderBox 36 | import ds.dbtests.db.objectbox.UserBox 37 | import ds.dbtests.db.orma.OrderOrma 38 | import ds.dbtests.db.orma.OrmaDatabase 39 | import ds.dbtests.db.orma.UserOrma 40 | import ds.dbtests.db.ormlite.OrderOrmLite 41 | import ds.dbtests.db.ormlite.OrmLiteDB 42 | import ds.dbtests.db.ormlite.UserOrmLite 43 | import ds.dbtests.db.realm.OrderRealm 44 | import ds.dbtests.db.realm.UserRealm 45 | import ds.dbtests.db.requery.Models 46 | import ds.dbtests.db.requery.OrderRequeryEntity 47 | import ds.dbtests.db.requery.UserRequeryEntity 48 | import ds.dbtests.db.room.AppDatabase 49 | import ds.dbtests.db.room.OrderRoom 50 | import ds.dbtests.db.room.UserRoom 51 | import ds.dbtests.db.snappydb.OrderSnappy 52 | import ds.dbtests.db.snappydb.UserSnappy 53 | import io.objectbox.BoxStore 54 | import io.reactivex.Observable.create 55 | import io.reactivex.android.schedulers.AndroidSchedulers 56 | import io.reactivex.schedulers.Schedulers 57 | import io.realm.Realm 58 | import io.realm.RealmConfiguration 59 | import io.requery.Persistable 60 | import io.requery.android.sqlite.DatabaseSource 61 | import io.requery.sql.EntityDataStore 62 | import io.requery.sql.TableCreationMode 63 | import kotterknife.bindView 64 | import java.util.* 65 | import java.util.concurrent.Semaphore 66 | 67 | class MainActivity : AppCompatActivity() { 68 | companion object { 69 | const val ITERATIONS = 99 70 | const val ORDERS = 99 71 | const val DESCRIPTION = """Once upon a midnight dreary, while I pondered, weak and weary, 72 | Over many a quaint and curious volume of forgotten lore, 73 | While I nodded, nearly napping, suddenly there came a tapping, 74 | As of some one gently rapping, rapping at my chamber door. 75 | "'Tis some visitor," I muttered, "tapping at my chamber door- 76 | Only this, and nothing more.""" 77 | @JvmField val names: Array = arrayOf("Leonardo", "Donatello", "Raphael", "Michaelangelo") 78 | @JvmField val ages: Array = Array(100, { it }) 79 | } 80 | 81 | 82 | private lateinit var greenDao: DaoSession 83 | private lateinit var ormLite: OrmLiteDB 84 | private lateinit var realm: Realm 85 | private lateinit var snappy: DB 86 | private lateinit var orma: OrmaDatabase 87 | private lateinit var requery: EntityDataStore 88 | private var firebase = FirebaseDatabase.getInstance().reference 89 | private lateinit var boxStore: BoxStore 90 | private lateinit var room: AppDatabase 91 | 92 | 93 | private var memory: MutableList = arrayListOf() 94 | private var realmConfig: RealmConfiguration? = null 95 | 96 | private val textView by bindView(R.id.text) 97 | 98 | 99 | override fun onCreate(savedInstanceState: Bundle?) { 100 | super.onCreate(savedInstanceState) 101 | setContentView(R.layout.activity_main) 102 | 103 | initGreenDao() 104 | initOrmLite() 105 | initRealm() 106 | initDBFlow() 107 | initSnappy() 108 | initOrma() 109 | initFirebase() 110 | initRequery() 111 | initObjectBox() 112 | initRoom() 113 | } 114 | 115 | private fun initRoom() { 116 | room = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "room-db").build() 117 | } 118 | 119 | private fun initObjectBox() { 120 | boxStore = MyObjectBox.builder().androidContext(App.instance).build() 121 | } 122 | 123 | private fun initRequery() { 124 | val source = DatabaseSource(this, Models.DEFAULT, "requery_db", 2) 125 | source.setTableCreationMode(TableCreationMode.DROP_CREATE) 126 | //val configuration = ConfigurationBuilder(source, Models.DEFAULT).build(); 127 | val configuration = source.configuration 128 | requery = EntityDataStore(configuration) 129 | } 130 | 131 | private fun initOrma() { 132 | orma = OrmaDatabase.builder(this) 133 | .readOnMainThread(AccessThreadConstraint.WARNING) // optional 134 | .writeOnMainThread(AccessThreadConstraint.FATAL) // optional 135 | .trace(false) 136 | .foreignKeys(false) 137 | .name("orma_db") 138 | .build() 139 | } 140 | 141 | private fun initSnappy() { 142 | snappy = DBFactory.open(this) 143 | } 144 | 145 | private fun initDBFlow() { 146 | // nothing to init 147 | } 148 | 149 | private fun initRealm() { 150 | // nothing to init 151 | Realm.init(this) 152 | realmConfig = RealmConfiguration.Builder().build() 153 | } 154 | 155 | private fun initOrmLite() { 156 | ormLite = OrmLiteDB.instance 157 | } 158 | 159 | private fun initFirebase() { 160 | firebase.database.goOffline() 161 | } 162 | 163 | 164 | private fun initGreenDao() { 165 | val helper = DaoMaster.DevOpenHelper(this, "greendao_db", null) 166 | val db = helper.writableDatabase 167 | val daoMaster = DaoMaster(db) 168 | greenDao = daoMaster.newSession() 169 | } 170 | 171 | 172 | private fun runTests() { 173 | logThread() 174 | message("Run test with $ITERATIONS users, $ORDERS orders in each user.\nPlease wait until 'done' message") 175 | create { 176 | realm = Realm.getInstance(realmConfig) 177 | 178 | 179 | it.onNext(TestResult(null, "Clean DB", profile { cleanAll() })) 180 | 181 | it.onNext(TestResult("Room", 182 | "Room write test", profile { boxStore.runInTx { roomWriteTest() } }, 183 | "Room full read test", profile { boxStore.runInReadTx { roomReadTest() } })) 184 | 185 | it.onNext(TestResult("ObjectBox", 186 | "ObjectBox write test", profile { boxStore.runInTx { objectBoxWriteTestNoSql() } }, 187 | "ObjectBox full read test", profile { boxStore.runInReadTx { objectBoxReadTestNoSql() } })) 188 | 189 | /*it.onNext(TestResult("Firebase", 190 | "Firebase write test", profile { firebaseWriteTest() }, 191 | "Firebase full read test", profile { firebaseReadTest() }))*/ 192 | 193 | it.onNext(TestResult("Firebase (no relations)", 194 | "Firebase write test NoSql style", profile { firebaseWriteTestNoSql() }, 195 | "Firebase full read test NoSql style", profile { firebaseReadTestNoSql() })) 196 | 197 | it.onNext(TestResult("ReQuery", 198 | "ReQuery write test in transaction", profile { requery.runInTransaction { requeryWriteTest() } }, 199 | "ReQuery full read test", profile { requeryReadTest(false) })) 200 | 201 | it.onNext(TestResult("Orma", 202 | "Orma write test in transaction", profile { orma.transactionSync { ormaWriteTest() } }, 203 | "Orma read test", profile { ormaReadTest(false) })) 204 | 205 | it.onNext(TestResult("DBFlow", 206 | "DBFlow write test in transaction", profile { FlowManager.getDatabase(DBFlowDatabase.NAME).executeTransaction { dbflowWriteTest() } }, 207 | "DBFlow full read test", profile { dbflowReadTest(false) })) 208 | 209 | it.onNext(TestResult("GreenDAO", 210 | "GreenDao write test in transaction", profile { greenDao.runInTx { greenDaoWriteTest() } }, 211 | "GreenDao full read test", profile { greenDaoReadTest(false) })) 212 | 213 | it.onNext(TestResult("Realm (no relations)", 214 | "Realm write test in transaction", profile { realm.executeTransaction { realmWriteTest() } }, 215 | "Realm read test", profile { realmReadTest() })) 216 | 217 | it.onNext(TestResult("SnappyDB", 218 | "Snappy write test", profile { snappyWriteTest() }, 219 | "Snappy read test", profile { snappyReadTest() })) 220 | 221 | it.onNext(TestResult("ORMLite", 222 | "OrmLite write test in transaction", profile { ormLite.usersDao.callBatchTasks { ormLiteWriteTest() } }, 223 | "OrmLite read test", profile { ormLiteReadTest() })) 224 | 225 | it.onNext(TestResult("RAM", 226 | "Memory write test", profile { memoryWriteTest() }, 227 | "Memory read test", profile { memoryReadTest() })) 228 | 229 | realm.close() 230 | it.onComplete() 231 | } 232 | .subscribeOn(Schedulers.io()) 233 | .observeOn(AndroidSchedulers.mainThread()) 234 | .subscribe({ 235 | if (it.writeMessage != null) 236 | message("${it.writeMessage}: ${it.writeValue}ms") 237 | 238 | if (it.readMessage != null) 239 | message("${it.readMessage}: ${it.readValue}ms") 240 | 241 | if (it.title != null) 242 | ChartData.results.add(it) 243 | 244 | }, { 245 | it.printStackTrace() 246 | message("Failure") 247 | }, { 248 | message("done!") 249 | realm = Realm.getInstance(realmConfig) 250 | }) 251 | 252 | 253 | } 254 | 255 | private fun message(t: String) { 256 | runOnUiThread({ textView.text += "$t\n" }) 257 | } 258 | 259 | private fun profile(f: () -> Any?): Long { 260 | System.gc() 261 | val time = System.currentTimeMillis() 262 | f() 263 | return System.currentTimeMillis() - time 264 | } 265 | 266 | private fun cleanAll() { 267 | // greendao clean 268 | greenDao.userGreenDaoDao.deleteAll() 269 | greenDao.orderGreenDaoDao.deleteAll() 270 | 271 | // ormlite clean 272 | TableUtils.clearTable(ormLite.connectionSource, UserOrmLite::class.java) 273 | TableUtils.clearTable(ormLite.connectionSource, OrderOrmLite::class.java) 274 | 275 | // realm clean 276 | try { 277 | realm.executeTransaction { 278 | realm.delete(UserRealm::class.java) 279 | realm.delete(OrderRealm::class.java) 280 | Log.d("#", "realm size=${realm.where(OrderRealm::class.java).count()}") 281 | } 282 | } catch (e: Exception) { 283 | e.printStackTrace() 284 | } 285 | 286 | // delete dbflow 287 | Delete.tables(UserDBFlow::class.java, OrderDBFlow::class.java) 288 | 289 | // snappy clean 290 | snappy.del("user") 291 | snappy.del("order") 292 | 293 | // orma clean 294 | orma.deleteFromOrderOrma().execute(); 295 | orma.deleteFromUserOrma().execute(); 296 | 297 | // requery clean 298 | try { 299 | requery.delete(UserRequeryEntity::class.java).get().value() 300 | requery.delete(OrderRequeryEntity::class.java).get().value() 301 | } catch (e: Exception) { 302 | e.printStackTrace() 303 | } 304 | 305 | // firebase clean 306 | firebase.removeValue() 307 | 308 | // ObjectBox clean 309 | boxStore.boxFor(UserBox::class.java).removeAll() 310 | boxStore.boxFor(OrderBox::class.java).removeAll() 311 | 312 | // room 313 | room.orderDao().deleteAll() 314 | room.userDao().deleteAll() 315 | 316 | // clean memory 317 | memory.clear() 318 | } 319 | 320 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 321 | 322 | private fun objectBoxWriteTestNoSql() { 323 | val users = boxStore.boxFor(UserBox::class.java) 324 | val orders = boxStore.boxFor(OrderBox::class.java) 325 | for (i in 0..ITERATIONS) { 326 | val u = UserBox() 327 | u.name = names[i % names.size] 328 | u.age = ages[i % ages.size] 329 | u.height = 1.85 330 | u.description = DESCRIPTION 331 | u.login = "login" 332 | u.password = "password123" 333 | u.phone = "555-123-4567" 334 | u.sex = "male" 335 | 336 | for (k in 0..ORDERS) { 337 | val o = OrderBox() 338 | orders.attach(o) 339 | o.title = "${u.name}'s item" 340 | o.price = 99.95 341 | o.count = k % 2 + 1 342 | o.created = Date(System.currentTimeMillis()) 343 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 344 | o.description = DESCRIPTION 345 | o.user = u 346 | 347 | //u.orders.add(o) 348 | orders.put(o) 349 | } 350 | 351 | users.put(u) 352 | 353 | } 354 | } 355 | 356 | private fun objectBoxReadTestNoSql() { 357 | val usersBox = boxStore.boxFor(UserBox::class.java) 358 | val users = usersBox.all 359 | for ((i, u) in users.withIndex()) { 360 | val orders = u.orders 361 | //u.toString() 362 | for (o in orders) { 363 | } 364 | } 365 | } 366 | 367 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 368 | 369 | private fun firebaseWriteTest() { 370 | for (i in 0..ITERATIONS) { 371 | val u = UserFB() 372 | u.id = i.toLong() + 1 373 | u.name = names[i % names.size] 374 | u.age = ages[i % ages.size] 375 | u.height = 1.85 376 | u.description = DESCRIPTION 377 | u.login = "login" 378 | u.password = "password123" 379 | u.phone = "555-123-4567" 380 | u.sex = "male" 381 | 382 | for (k in 0..ORDERS) { 383 | val o = OrderFB() 384 | o.id = (i * (ORDERS + 1) + k + 1).toLong() 385 | o.title = "${u.name}'s item" 386 | o.price = 99.95 387 | o.count = k % 2 + 1 388 | o.created = System.currentTimeMillis() 389 | o.expiration = System.currentTimeMillis() + 1000 * 60 390 | o.description = DESCRIPTION 391 | o.userId = u.id 392 | 393 | // simulate some sort of relation since firebase doesnt support selects by field 394 | firebase.child("orders${u.id}").push().setValue(o) 395 | } 396 | 397 | firebase.child("users").push().setValue(u) 398 | 399 | } 400 | } 401 | 402 | private fun firebaseReadTest() { 403 | 404 | println("firebase start read") 405 | 406 | val semaphore = Semaphore(0) 407 | val users = mutableListOf() 408 | 409 | firebase.child("users").addListenerForSingleValueEvent(object : ValueEventListener { 410 | override fun onCancelled(e: DatabaseError) { 411 | println("firebase error! ${e.message}") 412 | } 413 | 414 | override fun onDataChange(data: DataSnapshot) { 415 | println("firebase users size ${data.childrenCount}") 416 | for (uData in data.children) { 417 | val u = uData.getValue(UserFB::class.java) 418 | //println("user id=${u.id} name=${u.name} orders=${u.orders.size}") 419 | users.add(u!!) 420 | } 421 | println("firebase users retrieved") 422 | semaphore.release() 423 | } 424 | 425 | }) 426 | semaphore.acquire() 427 | 428 | for (user in users) { 429 | firebase.child("orders${user.id}").addListenerForSingleValueEvent(object : ValueEventListener { 430 | override fun onCancelled(e: DatabaseError) { 431 | println("firebase error! ${e.message}") 432 | } 433 | 434 | override fun onDataChange(data: DataSnapshot) { 435 | //println("firebase orders size ${data.childrenCount} for user ${user.id}") 436 | for (order in data.children) { 437 | val o = order.getValue(OrderFB::class.java) 438 | //println("user id=${u.id} name=${u.name} orders=${u.orders.size}") 439 | } 440 | //println("firebase orders retrieved") 441 | semaphore.release() 442 | } 443 | 444 | 445 | }) 446 | semaphore.acquire() 447 | } 448 | println("firebase read end") 449 | } 450 | 451 | private fun firebaseWriteTestNoSql() { 452 | for (i in 0..ITERATIONS) { 453 | val u = UserFB() 454 | u.id = i.toLong() + 1 455 | u.name = names[i % names.size] 456 | u.age = ages[i % ages.size] 457 | u.height = 1.85 458 | u.description = DESCRIPTION 459 | u.login = "login" 460 | u.password = "password123" 461 | u.phone = "555-123-4567" 462 | u.sex = "male" 463 | 464 | for (k in 0..ORDERS) { 465 | val o = OrderFB() 466 | o.id = (i * (ORDERS + 1) + k + 1).toLong() 467 | o.title = "${u.name}'s item" 468 | o.price = 99.95 469 | o.count = k % 2 + 1 470 | o.created = System.currentTimeMillis() 471 | o.expiration = System.currentTimeMillis() + 1000 * 60 472 | o.description = DESCRIPTION 473 | o.userId = u.id 474 | 475 | // simulate some sort of relation since firebase doesnt support selects by field 476 | u.orders.add(o) 477 | } 478 | 479 | firebase.child("users").push().setValue(u) 480 | 481 | } 482 | } 483 | 484 | private fun firebaseReadTestNoSql() { 485 | val semaphore = Semaphore(0) 486 | 487 | firebase.child("users").addListenerForSingleValueEvent(object : ValueEventListener { 488 | override fun onCancelled(e: DatabaseError) { 489 | println("firebase error! ${e.message}") 490 | } 491 | 492 | override fun onDataChange(data: DataSnapshot) { 493 | println("firebase users size ${data.childrenCount}") 494 | for (uData in data.children) { 495 | val u = uData.getValue(UserFB::class.java) 496 | //println("user id=${u.id} name=${u.name} orders=${u.orders.size}") 497 | } 498 | println("firebase users retrieved") 499 | semaphore.release() 500 | } 501 | 502 | }) 503 | semaphore.acquire() 504 | 505 | } 506 | 507 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 508 | 509 | private fun logThread() { 510 | println("thread: ${Thread.currentThread().id}") 511 | } 512 | 513 | private fun roomWriteTest() = room.run { 514 | 515 | for (i in 0..ITERATIONS) { 516 | val u: UserRoom = UserRoom() 517 | u.name = names[i % names.size] 518 | u.age = ages[i % ages.size] 519 | u.height = 1.85 520 | u.description = DESCRIPTION 521 | u.login = "login" 522 | u.password = "password123" 523 | u.phone = "555-123-4567" 524 | u.sex = "male" 525 | 526 | val id = userDao().insert(u) 527 | //println("user id=$id") 528 | 529 | for (k in 0..ORDERS) { 530 | val o = OrderRoom() 531 | o.title = "${u.name}'s item" 532 | o.price = 99.95 533 | o.count = k % 2 + 1 534 | o.created = Date() 535 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 536 | o.description = DESCRIPTION 537 | o.userId = id 538 | orderDao().insert(o) 539 | } 540 | } 541 | 542 | } 543 | 544 | private fun roomReadTest() = room.run { 545 | val users = userDao().fetchAll() 546 | //println("room users ${users.size}") 547 | for (u in users) { 548 | val orders = orderDao().fetchOrders(u.id) 549 | //println("room orders ${orders.size}") 550 | } 551 | } 552 | 553 | private inline fun T.run(block: T.() -> Unit) { 554 | beginTransaction() 555 | block(this) 556 | setTransactionSuccessful() 557 | endTransaction() 558 | } 559 | 560 | 561 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 562 | 563 | private fun greenDaoWriteTest() { 564 | for (i in 0..ITERATIONS) { 565 | val u: UserGreenDao = UserGreenDao() 566 | u.name = names[i % names.size] 567 | u.age = ages[i % ages.size] 568 | u.height = 1.85 569 | u.description = DESCRIPTION 570 | u.login = "login" 571 | u.password = "password123" 572 | u.phone = "555-123-4567" 573 | u.sex = "male" 574 | greenDao.insert(u) 575 | for (k in 0..ORDERS) { 576 | val o = OrderGreenDao() 577 | o.title = "${u.name}'s item" 578 | o.price = 99.95 579 | o.count = k % 2 + 1 580 | o.created = Date() 581 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 582 | o.description = DESCRIPTION 583 | o.user = u 584 | greenDao.insert(o) 585 | } 586 | } 587 | } 588 | 589 | private fun greenDaoReadTest(lazy: Boolean) { 590 | greenDao.clear() 591 | val users = greenDao.userGreenDaoDao.loadAll() 592 | if (!lazy) 593 | for ((i, u) in users.withIndex()) { 594 | for (o in u.orders) { 595 | if (i == 0) { 596 | } 597 | } 598 | } 599 | } 600 | 601 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 602 | private fun ormLiteWriteTest() { 603 | for (i in 0..ITERATIONS) { 604 | val u: UserOrmLite = UserOrmLite() 605 | u.name = names[i % names.size] 606 | u.age = ages[i % ages.size] 607 | u.height = 1.85 608 | u.description = DESCRIPTION 609 | u.login = "login" 610 | u.password = "password123" 611 | u.phone = "555-123-4567" 612 | u.sex = "male" 613 | ormLite.usersDao.create(u) 614 | for (k in 0..ORDERS) { 615 | val o = OrderOrmLite() 616 | o.title = "${u.name}'s item" 617 | o.price = 99.95 618 | o.count = k % 2 + 1 619 | o.created = Date() 620 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 621 | o.description = DESCRIPTION 622 | o.user = u 623 | ormLite.ordersDao.create(o) 624 | } 625 | } 626 | 627 | } 628 | 629 | private fun ormLiteReadTest() { 630 | ormLite.usersDao.clearObjectCache() 631 | val users = ormLite.usersDao.queryForAll() 632 | for (u in users) { 633 | for ((i, o) in u.orders.withIndex()) { 634 | } 635 | } 636 | } 637 | 638 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 639 | private fun realmWriteTest() { 640 | for (i in 0..ITERATIONS) { 641 | val u = realm.createObject(UserRealm::class.java, i.toLong() + 1) 642 | u.name = names[i % names.size] 643 | u.age = ages[i % ages.size] 644 | u.height = 1.85 645 | u.description = DESCRIPTION 646 | u.login = "login" 647 | u.password = "password123" 648 | u.phone = "555-123-4567" 649 | u.sex = "male" 650 | for (k in 0..ORDERS) { 651 | val o = realm.createObject(OrderRealm::class.java, (i * (ORDERS + 1) + k + 1).toLong()) 652 | //val o = OrderRealm() 653 | o.title = "${u.name}'s item" 654 | o.price = 99.95 655 | o.count = k % 2 + 1 656 | o.created = Date() 657 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 658 | o.description = DESCRIPTION 659 | u.orders.add(o) 660 | //realm.copyToRealm(o) 661 | } 662 | } 663 | } 664 | 665 | private fun realmReadTest() { 666 | 667 | val users = realm.where(UserRealm::class.java).findAll() 668 | // must read all fields explicitly due to realm lazyness 669 | for ((i, u) in users.withIndex()) { 670 | u.age 671 | u.description 672 | u.height 673 | u.id 674 | u.login 675 | u.name 676 | u.password 677 | u.phone 678 | u.sex 679 | for (o in u.orders) { 680 | o.title 681 | o.count 682 | o.created 683 | o.description 684 | o.expiration 685 | o.id 686 | o.price 687 | } 688 | } 689 | } 690 | 691 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 692 | private fun dbflowWriteTest() { 693 | for (i in 0..ITERATIONS) { 694 | val u: UserDBFlow = UserDBFlow() 695 | u.name = names[i % names.size] 696 | u.age = ages[i % ages.size] 697 | u.height = 1.85 698 | u.description = DESCRIPTION 699 | u.login = "login" 700 | u.password = "password123" 701 | u.phone = "555-123-4567" 702 | u.sex = "male" 703 | u.save() 704 | 705 | for (k in 0..ORDERS) { 706 | val o = OrderDBFlow() 707 | o.title = "${u.name}'s item" 708 | o.price = 99.95 709 | o.count = k % 2 + 1 710 | o.created = Date() 711 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 712 | o.description = DESCRIPTION 713 | o.setUser(u) 714 | o.save() 715 | } 716 | } 717 | } 718 | 719 | private fun dbflowReadTest(lazy: Boolean) { 720 | 721 | val users = Select() 722 | .from(UserDBFlow::class.java) 723 | .where() 724 | .queryList() 725 | 726 | if (!lazy) { 727 | //println("not lazy!") 728 | for ((i, u) in users.withIndex()) { 729 | for (o in u.orders) { 730 | } 731 | } 732 | } 733 | } 734 | 735 | private fun ormaWriteTest() { 736 | val userInserter = orma.prepareInsertIntoUserOrma() 737 | val orderInserter = orma.prepareInsertIntoOrderOrma(); 738 | 739 | for (i in 0..ITERATIONS) { 740 | val u = UserOrma() 741 | u.name = names[i % names.size] 742 | u.age = ages[i % ages.size] 743 | u.height = 1.85 744 | u.description = DESCRIPTION 745 | u.login = "login" 746 | u.password = "password123" 747 | u.phone = "555-123-4567" 748 | u.sex = "male" 749 | val userId = userInserter.execute(u) 750 | 751 | for (k in 0..ORDERS) { 752 | val o = OrderOrma() 753 | o.title = "${u.name}'s item" 754 | o.price = 99.95 755 | o.count = k % 2 + 1 756 | o.created = Date() 757 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 758 | o.description = DESCRIPTION 759 | o.user = SingleAssociation.just(userId, u) 760 | orderInserter.execute(o) 761 | } 762 | } 763 | } 764 | 765 | 766 | private fun ormaReadTest(lazy: Boolean) { 767 | 768 | val users = orma.selectFromUserOrma().toList() 769 | 770 | if (!lazy) { 771 | println("orma full read") 772 | for ((i, u) in users.withIndex()) { 773 | val orders = u.getOrders(orma).toList() 774 | } 775 | } 776 | } 777 | 778 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 779 | 780 | private fun requeryWriteTest() { 781 | println("requery write") 782 | for (i in 0..ITERATIONS) { 783 | var u = UserRequeryEntity() 784 | u.name = names[i % names.size] 785 | u.age = ages[i % ages.size] 786 | u.height = 1.85 787 | u.description = DESCRIPTION 788 | u.login = "login" 789 | u.password = "password123" 790 | u.phone = "555-123-4567" 791 | u.sex = "male" 792 | u = requery.insert(u) 793 | 794 | for (k in 0..ORDERS) { 795 | val o = OrderRequeryEntity() 796 | o.title = "${u.name}'s item" 797 | o.price = 99.95 798 | o.count = k % 2 + 1 799 | o.created = Date() 800 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 801 | o.description = DESCRIPTION 802 | o.user = u 803 | requery.insert(o) 804 | } 805 | 806 | } 807 | } 808 | 809 | private fun requeryReadTest(lazy: Boolean) { 810 | val users = requery.select(UserRequeryEntity::class.java).get().toList() 811 | println("requery users=${users.size}") 812 | if (!lazy) { 813 | println("requery full read") 814 | for ((i, u) in users.withIndex()) { 815 | val orders = u.getOrders() 816 | for (order in orders) { 817 | } 818 | } 819 | } 820 | } 821 | 822 | 823 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 824 | private fun snappyWriteTest() { 825 | for (i in 0..ITERATIONS) { 826 | val u: UserSnappy = UserSnappy() 827 | u.id = i.toLong() + 1 828 | u.name = names[i % names.size] 829 | u.age = ages[i % ages.size] 830 | u.height = 1.85 831 | u.description = DESCRIPTION 832 | u.login = "login" 833 | u.password = "password123" 834 | u.phone = "555-123-4567" 835 | u.sex = "male" 836 | 837 | snappy.put("user${u.id}", u) 838 | 839 | for (k in 0..ORDERS) { 840 | val o = OrderSnappy() 841 | o.id = (i * (ORDERS + 1) + k + 1).toLong() 842 | o.title = "${u.name}'s item" 843 | o.price = 99.95 844 | o.count = k % 2 + 1 845 | o.created = Date() 846 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 847 | o.description = DESCRIPTION 848 | 849 | val key = "order${u.id}:${o.id}" 850 | snappy.put(key, o) 851 | } 852 | 853 | 854 | } 855 | } 856 | 857 | private fun snappyReadTest() { 858 | val userKeys = snappy.findKeys("user") 859 | for (key in userKeys) { 860 | val user = snappy.getObject(key, UserSnappy::class.java) 861 | val orderKey = "order${user.id}:" 862 | val ordersKeys = snappy.findKeys(orderKey) 863 | for (key in ordersKeys) { 864 | val order = snappy.getObject(key, OrderSnappy::class.java) 865 | } 866 | } 867 | 868 | } 869 | 870 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 871 | private fun memoryWriteTest() { 872 | for (i in 0..ITERATIONS) { 873 | val u: UserSnappy = UserSnappy() 874 | u.id = i.toLong() + 1 875 | u.name = names[i % names.size] 876 | u.age = ages[i % ages.size] 877 | u.height = 1.85 878 | u.description = DESCRIPTION 879 | u.login = "login" 880 | u.password = "password123" 881 | u.phone = "555-123-4567" 882 | u.sex = "male" 883 | 884 | for (k in 0..ORDERS) { 885 | val o = OrderSnappy() 886 | o.id = (i * (ORDERS + 1) + k + 1).toLong() 887 | o.title = "${u.name}'s item" 888 | o.price = 99.95 889 | o.count = k % 2 + 1 890 | o.created = Date() 891 | o.expiration = Date(System.currentTimeMillis() + 1000 * 60) 892 | o.description = DESCRIPTION 893 | o.user = u 894 | u.addOrder(o) 895 | } 896 | 897 | memory.add(u) 898 | 899 | } 900 | } 901 | 902 | private fun memoryReadTest() { 903 | 904 | for (u in memory) { 905 | for ((i, o) in u.orders.withIndex()) { 906 | } 907 | } 908 | } 909 | 910 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 911 | 912 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 913 | menuInflater.inflate(R.menu.main, menu) 914 | return super.onCreateOptionsMenu(menu) 915 | } 916 | 917 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 918 | when (item.itemId) { 919 | R.id.run -> runTests() 920 | R.id.chart -> startActivity(Intent(this, ChartActivity::class.java)) 921 | } 922 | return super.onOptionsItemSelected(item) 923 | } 924 | 925 | override fun onDestroy() { 926 | super.onDestroy() 927 | ormLite.close() 928 | greenDao.database.close() 929 | } 930 | } 931 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/Test.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | interface Test { 4 | 5 | fun writeTest() 6 | fun readTest(lazy: Boolean) 7 | fun init() 8 | fun clean() 9 | } 10 | 11 | abstract class TestBase() : Test { 12 | init { 13 | init() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/TestResult.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests 2 | 3 | //@Parcel 4 | data class TestResult( 5 | val title: String?, 6 | val writeMessage: String?, 7 | val writeValue: Long = 0, 8 | val readMessage: String? = null, 9 | val readValue: Long = 0) 10 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/Order.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db 2 | 3 | import java.util.* 4 | 5 | interface Order { 6 | var id: Long? 7 | var title: String? 8 | var description: String? 9 | var expiration: Date? 10 | var created: Date? 11 | var count: Int 12 | var price: Double 13 | var user: User? 14 | 15 | //override fun toString(): String = "id=$id item=$title price=$price" 16 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/User.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db 2 | 3 | interface User { 4 | var id: Long? 5 | var name: String? 6 | var login: String? 7 | var password: String? 8 | var description: String? 9 | var phone: String? 10 | var sex: String? 11 | var age: Int 12 | var height: Double 13 | var orders: Collection 14 | 15 | //override fun toString(): String = "id=$id name=$name age=$age orders=${orders.size()}" 16 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/dbflow/DBFlowDatabase.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.dbflow; 2 | 3 | import com.raizlabs.android.dbflow.annotation.Database; 4 | 5 | @Database( 6 | name = DBFlowDatabase.NAME, 7 | version = DBFlowDatabase.VERSION 8 | ) 9 | public class DBFlowDatabase { 10 | 11 | public static final String NAME = "dbflow_db"; 12 | public static final int VERSION = 4; 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/dbflow/OrderDBFlow.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.dbflow; 2 | 3 | 4 | import com.raizlabs.android.dbflow.annotation.Column; 5 | import com.raizlabs.android.dbflow.annotation.ForeignKey; 6 | import com.raizlabs.android.dbflow.annotation.Index; 7 | import com.raizlabs.android.dbflow.annotation.PrimaryKey; 8 | import com.raizlabs.android.dbflow.annotation.Table; 9 | import com.raizlabs.android.dbflow.structure.BaseModel; 10 | 11 | import java.util.Date; 12 | 13 | @Table(database = DBFlowDatabase.class, cachingEnabled = true) 14 | //@ModelContainer 15 | public class OrderDBFlow extends BaseModel { 16 | 17 | @PrimaryKey(autoincrement = true) public long id; 18 | @Column public String title; 19 | @Column public String description; 20 | @Column public Date expiration; 21 | @Column public Date created; 22 | @Column public int count; 23 | @Column public double price; 24 | 25 | //@Column long user_id; 26 | //private UserDBFlow user; 27 | 28 | @ForeignKey(stubbedRelationship = true, saveForeignKeyModel = false) 29 | @Index 30 | public UserDBFlow user; 31 | 32 | public void setUser(UserDBFlow u) { 33 | user = u; 34 | } 35 | 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/dbflow/UserDBFlow.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.dbflow; 2 | 3 | import com.raizlabs.android.dbflow.annotation.*; 4 | import com.raizlabs.android.dbflow.sql.language.SQLite; 5 | import com.raizlabs.android.dbflow.sql.language.Where; 6 | import com.raizlabs.android.dbflow.structure.BaseModel; 7 | 8 | import java.util.List; 9 | 10 | @Table(database = DBFlowDatabase.class, cachingEnabled = true) 11 | //@ModelContainer 12 | public class UserDBFlow extends BaseModel { 13 | 14 | @PrimaryKey(autoincrement = true) public long id; 15 | @Column public String name; 16 | @Column public String login; 17 | @Column public String password; 18 | @Column public String description; 19 | @Column public String phone; 20 | @Column public String sex; 21 | @Column public int age; 22 | @Column public double height; 23 | 24 | List orders; 25 | 26 | @OneToMany(methods = {}) 27 | public List getOrders() { 28 | if (orders == null) { 29 | Where w = SQLite.select() 30 | .from(OrderDBFlow.class) 31 | .where(OrderDBFlow_Table.user_id.eq(id)); 32 | //Log.v("query=", w.getQuery()); 33 | orders = w.queryList(); 34 | 35 | } 36 | return orders; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/firebase/OrderFB.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.firebase; 2 | 3 | public class OrderFB { 4 | 5 | public long id; 6 | public String title; 7 | public double price; 8 | public int count; 9 | public long created; 10 | public long expiration; 11 | public String description; 12 | 13 | public long userId; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/firebase/UserFB.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.firebase; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class UserFB { 7 | 8 | public long id; 9 | public int age; 10 | public double height; 11 | public String name; 12 | public String login; 13 | public String password; 14 | public String sex; 15 | public String description; 16 | public String phone; 17 | 18 | public List orders; 19 | 20 | public UserFB() { 21 | this.orders = new ArrayList<>(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/greendao/OrderGreenDao.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.greendao; 2 | 3 | import org.greenrobot.greendao.DaoException; 4 | import org.greenrobot.greendao.annotation.Entity; 5 | import org.greenrobot.greendao.annotation.Generated; 6 | import org.greenrobot.greendao.annotation.Id; 7 | import org.greenrobot.greendao.annotation.Index; 8 | import org.greenrobot.greendao.annotation.NotNull; 9 | import org.greenrobot.greendao.annotation.ToOne; 10 | 11 | import ds.dbtests.db.User; 12 | 13 | // THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS 14 | 15 | // KEEP INCLUDES - put your custom includes here 16 | // KEEP INCLUDES END 17 | /** 18 | * Entity mapped to table "ORDER_GREEN_DAO". 19 | */ 20 | @Entity(active = true) 21 | public class OrderGreenDao implements /*java.io.Serializable,*/ ds.dbtests.db.Order { 22 | 23 | @Id(autoincrement = true) 24 | private Long id; 25 | private String title; 26 | private double price; 27 | private int count; 28 | 29 | @NotNull 30 | private java.util.Date created; 31 | 32 | @NotNull 33 | private java.util.Date expiration; 34 | 35 | @NotNull 36 | private String description; 37 | 38 | @Index 39 | private long userId; 40 | 41 | /** Used to resolve relations */ 42 | @Generated(hash = 2040040024) 43 | private transient DaoSession daoSession; 44 | /** Used for active entity operations. */ 45 | @Generated(hash = 1417876764) 46 | private transient OrderGreenDaoDao myDao; 47 | @ToOne(joinProperty = "userId") 48 | private UserGreenDao user; 49 | 50 | @Generated(hash = 251390918) 51 | private transient Long user__resolvedKey; 52 | 53 | 54 | 55 | // KEEP FIELDS - put your custom fields here 56 | // KEEP FIELDS END 57 | 58 | @Generated(hash = 1805740375) 59 | public OrderGreenDao() { 60 | } 61 | 62 | public OrderGreenDao(Long id) { 63 | this.id = id; 64 | } 65 | 66 | @Generated(hash = 1769523073) 67 | public OrderGreenDao(Long id, String title, double price, int count, @NotNull java.util.Date created, @NotNull java.util.Date expiration, 68 | @NotNull String description, long userId) { 69 | this.id = id; 70 | this.title = title; 71 | this.price = price; 72 | this.count = count; 73 | this.created = created; 74 | this.expiration = expiration; 75 | this.description = description; 76 | this.userId = userId; 77 | } 78 | 79 | public Long getId() { 80 | return id; 81 | } 82 | 83 | public void setId(Long id) { 84 | this.id = id; 85 | } 86 | 87 | public String getTitle() { 88 | return title; 89 | } 90 | 91 | public void setTitle(String title) { 92 | this.title = title; 93 | } 94 | 95 | public double getPrice() { 96 | return price; 97 | } 98 | 99 | public void setPrice(double price) { 100 | this.price = price; 101 | } 102 | 103 | public int getCount() { 104 | return count; 105 | } 106 | 107 | public void setCount(int count) { 108 | this.count = count; 109 | } 110 | 111 | @NotNull 112 | public java.util.Date getCreated() { 113 | return created; 114 | } 115 | 116 | /** Not-null value; ensure this value is available before it is saved to the database. */ 117 | public void setCreated(@NotNull java.util.Date created) { 118 | this.created = created; 119 | } 120 | 121 | @NotNull 122 | public java.util.Date getExpiration() { 123 | return expiration; 124 | } 125 | 126 | /** Not-null value; ensure this value is available before it is saved to the database. */ 127 | public void setExpiration(@NotNull java.util.Date expiration) { 128 | this.expiration = expiration; 129 | } 130 | 131 | @NotNull 132 | public String getDescription() { 133 | return description; 134 | } 135 | 136 | /** Not-null value; ensure this value is available before it is saved to the database. */ 137 | public void setDescription(@NotNull String description) { 138 | this.description = description; 139 | } 140 | 141 | public long getUserId() { 142 | return userId; 143 | } 144 | 145 | public void setUserId(long userId) { 146 | this.userId = userId; 147 | } 148 | 149 | /** To-one relationship, resolved on first access. */ 150 | @Generated(hash = 462796126) 151 | public UserGreenDao getUser() { 152 | long __key = this.userId; 153 | if (user__resolvedKey == null || !user__resolvedKey.equals(__key)) { 154 | final DaoSession daoSession = this.daoSession; 155 | if (daoSession == null) { 156 | throw new DaoException("Entity is detached from DAO context"); 157 | } 158 | UserGreenDaoDao targetDao = daoSession.getUserGreenDaoDao(); 159 | UserGreenDao userNew = targetDao.load(__key); 160 | synchronized (this) { 161 | user = userNew; 162 | user__resolvedKey = __key; 163 | } 164 | } 165 | return user; 166 | } 167 | 168 | /** called by internal mechanisms, do not call yourself. */ 169 | @Generated(hash = 355604469) 170 | public void setUser(@NotNull UserGreenDao user) { 171 | if (user == null) { 172 | throw new DaoException("To-one property 'userId' has not-null constraint; cannot set to-one to null"); 173 | } 174 | synchronized (this) { 175 | this.user = user; 176 | userId = user.getId(); 177 | user__resolvedKey = userId; 178 | } 179 | } 180 | 181 | /** 182 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. 183 | * Entity must attached to an entity context. 184 | */ 185 | @Generated(hash = 128553479) 186 | public void delete() { 187 | if (myDao == null) { 188 | throw new DaoException("Entity is detached from DAO context"); 189 | } 190 | myDao.delete(this); 191 | } 192 | 193 | /** 194 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. 195 | * Entity must attached to an entity context. 196 | */ 197 | @Generated(hash = 713229351) 198 | public void update() { 199 | if (myDao == null) { 200 | throw new DaoException("Entity is detached from DAO context"); 201 | } 202 | myDao.update(this); 203 | } 204 | 205 | /** 206 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. 207 | * Entity must attached to an entity context. 208 | */ 209 | @Generated(hash = 1942392019) 210 | public void refresh() { 211 | if (myDao == null) { 212 | throw new DaoException("Entity is detached from DAO context"); 213 | } 214 | myDao.refresh(this); 215 | } 216 | 217 | // KEEP METHODS - put your custom methods here 218 | @Override 219 | public void setUser(final User user) { 220 | setUser((UserGreenDao) user); 221 | } 222 | // KEEP METHODS END 223 | 224 | /** called by internal mechanisms, do not call yourself. */ 225 | @Generated(hash = 453244264) 226 | public void __setDaoSession(DaoSession daoSession) { 227 | this.daoSession = daoSession; 228 | myDao = daoSession != null ? daoSession.getOrderGreenDaoDao() : null; 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/greendao/UserGreenDao.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.greendao; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import org.greenrobot.greendao.DaoException; 6 | import org.greenrobot.greendao.annotation.Entity; 7 | import org.greenrobot.greendao.annotation.Generated; 8 | import org.greenrobot.greendao.annotation.Id; 9 | import org.greenrobot.greendao.annotation.JoinProperty; 10 | import org.greenrobot.greendao.annotation.ToMany; 11 | 12 | import java.util.Collection; 13 | import java.util.List; 14 | 15 | import ds.dbtests.db.Order; 16 | 17 | // THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS 18 | 19 | // KEEP INCLUDES - put your custom includes here 20 | // KEEP INCLUDES END 21 | 22 | /** 23 | * Entity mapped to table "USER_GREEN_DAO". 24 | */ 25 | @Entity(active = true) 26 | public class UserGreenDao implements /*java.io.Serializable,*/ ds.dbtests.db.User { 27 | 28 | @Id(autoincrement = true) 29 | private Long id; 30 | private int age; 31 | private double height; 32 | private String name; 33 | private String login; 34 | private String password; 35 | private String sex; 36 | private String description; 37 | private String phone; 38 | 39 | /** Used to resolve relations */ 40 | @Generated(hash = 2040040024) 41 | private transient DaoSession daoSession; 42 | /** Used for active entity operations. */ 43 | @Generated(hash = 1911154127) 44 | private transient UserGreenDaoDao myDao; 45 | @ToMany(joinProperties = { 46 | @JoinProperty(name = "id", referencedName = "userId") 47 | }) 48 | private List orderGreenDaoList; 49 | 50 | // KEEP FIELDS - put your custom fields here 51 | // KEEP FIELDS END 52 | 53 | @Generated(hash = 1822745106) 54 | public UserGreenDao() { 55 | } 56 | 57 | public UserGreenDao(Long id) { 58 | this.id = id; 59 | } 60 | 61 | @Generated(hash = 1637278874) 62 | public UserGreenDao(Long id, int age, double height, String name, String login, String password, String sex, 63 | String description, String phone) { 64 | this.id = id; 65 | this.age = age; 66 | this.height = height; 67 | this.name = name; 68 | this.login = login; 69 | this.password = password; 70 | this.sex = sex; 71 | this.description = description; 72 | this.phone = phone; 73 | } 74 | 75 | public Long getId() { 76 | return id; 77 | } 78 | 79 | public void setId(Long id) { 80 | this.id = id; 81 | } 82 | 83 | public int getAge() { 84 | return age; 85 | } 86 | 87 | public void setAge(int age) { 88 | this.age = age; 89 | } 90 | 91 | public double getHeight() { 92 | return height; 93 | } 94 | 95 | public void setHeight(double height) { 96 | this.height = height; 97 | } 98 | 99 | public String getName() { 100 | return name; 101 | } 102 | 103 | public void setName(String name) { 104 | this.name = name; 105 | } 106 | 107 | public String getLogin() { 108 | return login; 109 | } 110 | 111 | public void setLogin(String login) { 112 | this.login = login; 113 | } 114 | 115 | public String getPassword() { 116 | return password; 117 | } 118 | 119 | public void setPassword(String password) { 120 | this.password = password; 121 | } 122 | 123 | public String getSex() { 124 | return sex; 125 | } 126 | 127 | public void setSex(String sex) { 128 | this.sex = sex; 129 | } 130 | 131 | public String getDescription() { 132 | return description; 133 | } 134 | 135 | public void setDescription(String description) { 136 | this.description = description; 137 | } 138 | 139 | public String getPhone() { 140 | return phone; 141 | } 142 | 143 | public void setPhone(String phone) { 144 | this.phone = phone; 145 | } 146 | 147 | /** 148 | * To-many relationship, resolved on first access (and after reset). 149 | * Changes to to-many relations are not persisted, make changes to the target entity. 150 | */ 151 | @Generated(hash = 1191831640) 152 | public List getOrderGreenDaoList() { 153 | if (orderGreenDaoList == null) { 154 | final DaoSession daoSession = this.daoSession; 155 | if (daoSession == null) { 156 | throw new DaoException("Entity is detached from DAO context"); 157 | } 158 | OrderGreenDaoDao targetDao = daoSession.getOrderGreenDaoDao(); 159 | List orderGreenDaoListNew = targetDao._queryUserGreenDao_OrderGreenDaoList(id); 160 | synchronized (this) { 161 | if (orderGreenDaoList == null) { 162 | orderGreenDaoList = orderGreenDaoListNew; 163 | } 164 | } 165 | } 166 | return orderGreenDaoList; 167 | } 168 | 169 | /** Resets a to-many relationship, making the next get call to query for a fresh result. */ 170 | @Generated(hash = 932226337) 171 | public synchronized void resetOrderGreenDaoList() { 172 | orderGreenDaoList = null; 173 | } 174 | 175 | /** 176 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. 177 | * Entity must attached to an entity context. 178 | */ 179 | @Generated(hash = 128553479) 180 | public void delete() { 181 | if (myDao == null) { 182 | throw new DaoException("Entity is detached from DAO context"); 183 | } 184 | myDao.delete(this); 185 | } 186 | 187 | /** 188 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. 189 | * Entity must attached to an entity context. 190 | */ 191 | @Generated(hash = 713229351) 192 | public void update() { 193 | if (myDao == null) { 194 | throw new DaoException("Entity is detached from DAO context"); 195 | } 196 | myDao.update(this); 197 | } 198 | 199 | /** 200 | * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. 201 | * Entity must attached to an entity context. 202 | */ 203 | @Generated(hash = 1942392019) 204 | public void refresh() { 205 | if (myDao == null) { 206 | throw new DaoException("Entity is detached from DAO context"); 207 | } 208 | myDao.refresh(this); 209 | } 210 | 211 | // KEEP METHODS - put your custom methods here 212 | @SuppressWarnings("unchecked") 213 | @Override 214 | @NonNull 215 | public List getOrders() { 216 | return (List) (Object) getOrderGreenDaoList(); 217 | } 218 | 219 | 220 | @Override 221 | public void setOrders(final Collection list) { 222 | orderGreenDaoList = (List) list; 223 | } 224 | 225 | /** called by internal mechanisms, do not call yourself. */ 226 | @Generated(hash = 767560106) 227 | public void __setDaoSession(DaoSession daoSession) { 228 | this.daoSession = daoSession; 229 | myDao = daoSession != null ? daoSession.getUserGreenDaoDao() : null; 230 | } 231 | 232 | // KEEP METHODS END 233 | 234 | } 235 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/objectbox/OrderBox.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.objectbox; 2 | 3 | import java.util.Date; 4 | 5 | import io.objectbox.BoxStore; 6 | import io.objectbox.annotation.Entity; 7 | import io.objectbox.annotation.Generated; 8 | import io.objectbox.annotation.Id; 9 | import io.objectbox.annotation.Relation; 10 | import io.objectbox.annotation.apihint.Internal; 11 | import io.objectbox.exception.DbDetachedException; 12 | import io.objectbox.relation.ToOne; 13 | 14 | 15 | @Entity 16 | public class OrderBox /*implements Order*/ { 17 | 18 | @Id 19 | private long id; 20 | private String title; 21 | private double price; 22 | private int count; 23 | private Date created; 24 | private Date expiration; 25 | private String description; 26 | @Relation 27 | private UserBox user; 28 | long userId; 29 | /** Used to resolve relations */ 30 | @Internal 31 | @Generated(hash = 1307364262) 32 | transient BoxStore __boxStore; 33 | @Generated(hash = 861401677) 34 | public OrderBox(long id, String title, double price, int count, Date created, 35 | Date expiration, String description, long userId) { 36 | this.id = id; 37 | this.title = title; 38 | this.price = price; 39 | this.count = count; 40 | this.created = created; 41 | this.expiration = expiration; 42 | this.description = description; 43 | this.userId = userId; 44 | } 45 | @Generated(hash = 851799299) 46 | public OrderBox() { 47 | } 48 | public long getId() { 49 | return id; 50 | } 51 | public void setId(long id) { 52 | this.id = id; 53 | } 54 | public String getTitle() { 55 | return title; 56 | } 57 | public void setTitle(String title) { 58 | this.title = title; 59 | } 60 | public double getPrice() { 61 | return price; 62 | } 63 | public void setPrice(double price) { 64 | this.price = price; 65 | } 66 | public int getCount() { 67 | return count; 68 | } 69 | public void setCount(int count) { 70 | this.count = count; 71 | } 72 | public Date getCreated() { 73 | return created; 74 | } 75 | public void setCreated(Date created) { 76 | this.created = created; 77 | } 78 | public Date getExpiration() { 79 | return expiration; 80 | } 81 | public void setExpiration(Date expiration) { 82 | this.expiration = expiration; 83 | } 84 | public String getDescription() { 85 | return description; 86 | } 87 | public void setDescription(String description) { 88 | this.description = description; 89 | } 90 | public long getUserId() { 91 | return userId; 92 | } 93 | public void setUserId(long userId) { 94 | this.userId = userId; 95 | } 96 | @Internal 97 | @Generated(hash = 1214004309) 98 | private transient ToOne user__toOne; 99 | /** See {@link io.objectbox.relation.ToOne} for details. */ 100 | @Generated(hash = 1060655990) 101 | public synchronized ToOne getUser__toOne() { 102 | if (user__toOne == null) { 103 | user__toOne = new ToOne<>(this, OrderBox_.userId, UserBox.class); 104 | } 105 | return user__toOne; 106 | } 107 | /** To-one relationship, resolved on first access. */ 108 | @Generated(hash = 606673029) 109 | public UserBox getUser() { 110 | user = getUser__toOne().getTarget(this.userId); 111 | return user; 112 | } 113 | /** Set the to-one relation including its ID property. */ 114 | @Generated(hash = 1227882430) 115 | public void setUser(UserBox user) { 116 | getUser__toOne().setTarget(user); 117 | this.user = user; 118 | } 119 | /** 120 | * Removes entity from its object box. Entity must attached to an entity context. 121 | */ 122 | @Generated(hash = 1114511745) 123 | public void remove() { 124 | if (__boxStore == null) { 125 | throw new DbDetachedException(); 126 | } 127 | __boxStore.boxFor(OrderBox.class).remove(this); 128 | } 129 | /** 130 | * Puts the entity in its object box. 131 | * Entity must attached to an entity context. 132 | */ 133 | @Generated(hash = 1371990828) 134 | public void put() { 135 | if (__boxStore == null) { 136 | throw new DbDetachedException(); 137 | } 138 | __boxStore.boxFor(OrderBox.class).put(this); 139 | } 140 | 141 | 142 | 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/objectbox/UserBox.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.objectbox; 2 | 3 | import java.util.List; 4 | 5 | import io.objectbox.annotation.Entity; 6 | import io.objectbox.annotation.Id; 7 | import io.objectbox.annotation.Relation; 8 | import io.objectbox.annotation.Generated; 9 | import io.objectbox.Box; 10 | import io.objectbox.BoxStore; 11 | import io.objectbox.annotation.apihint.Internal; 12 | import io.objectbox.exception.DbDetachedException; 13 | import io.objectbox.exception.DbException; 14 | 15 | @Entity 16 | public class UserBox /*implements ds.dbtests.db.User*/ { 17 | 18 | @Id 19 | private long id; 20 | private int age; 21 | private double height; 22 | private String name; 23 | private String login; 24 | private String password; 25 | private String sex; 26 | private String description; 27 | private String phone; 28 | 29 | @Relation(idProperty = "userId") 30 | private List orders; 31 | /** Used to resolve relations */ 32 | @Internal 33 | @Generated(hash = 1307364262) 34 | transient BoxStore __boxStore; 35 | 36 | @Generated(hash = 556203250) 37 | public UserBox(long id, int age, double height, String name, String login, 38 | String password, String sex, String description, String phone) { 39 | this.id = id; 40 | this.age = age; 41 | this.height = height; 42 | this.name = name; 43 | this.login = login; 44 | this.password = password; 45 | this.sex = sex; 46 | this.description = description; 47 | this.phone = phone; 48 | } 49 | 50 | @Generated(hash = 1578460280) 51 | public UserBox() { 52 | } 53 | 54 | public long getId() { 55 | return id; 56 | } 57 | 58 | public void setId(long id) { 59 | this.id = id; 60 | } 61 | 62 | public int getAge() { 63 | return age; 64 | } 65 | 66 | public void setAge(int age) { 67 | this.age = age; 68 | } 69 | 70 | public double getHeight() { 71 | return height; 72 | } 73 | 74 | public void setHeight(double height) { 75 | this.height = height; 76 | } 77 | 78 | public String getName() { 79 | return name; 80 | } 81 | 82 | public void setName(String name) { 83 | this.name = name; 84 | } 85 | 86 | public String getLogin() { 87 | return login; 88 | } 89 | 90 | public void setLogin(String login) { 91 | this.login = login; 92 | } 93 | 94 | public String getPassword() { 95 | return password; 96 | } 97 | 98 | public void setPassword(String password) { 99 | this.password = password; 100 | } 101 | 102 | public String getSex() { 103 | return sex; 104 | } 105 | 106 | public void setSex(String sex) { 107 | this.sex = sex; 108 | } 109 | 110 | public String getDescription() { 111 | return description; 112 | } 113 | 114 | public void setDescription(String description) { 115 | this.description = description; 116 | } 117 | 118 | public String getPhone() { 119 | return phone; 120 | } 121 | 122 | public void setPhone(String phone) { 123 | this.phone = phone; 124 | } 125 | 126 | /** 127 | * To-many relationship, resolved on first access (and after reset). 128 | * Changes to to-many relations are not persisted, make changes to the target entity. 129 | */ 130 | @Generated(hash = 969548343) 131 | public List getOrders() { 132 | if (orders == null) { 133 | final BoxStore boxStore = this.__boxStore; 134 | if (boxStore == null) { 135 | throw new DbDetachedException(); 136 | } 137 | Box box = boxStore.boxFor(OrderBox.class); 138 | int targetTypeId = boxStore.getEntityTypeIdOrThrow(OrderBox.class); 139 | List ordersNew = box.getBacklinkEntities(targetTypeId, 140 | OrderBox_.userId, id); 141 | synchronized (this) { 142 | if (orders == null) { 143 | orders = ordersNew; 144 | } 145 | } 146 | } 147 | return orders; 148 | } 149 | 150 | /** Resets a to-many relationship, making the next get call to query for a fresh result. */ 151 | @Generated(hash = 1446109810) 152 | public synchronized void resetOrders() { 153 | orders = null; 154 | } 155 | 156 | /** 157 | * Removes entity from its object box. Entity must attached to an entity context. 158 | */ 159 | @Generated(hash = 1407782313) 160 | public void remove() { 161 | if (__boxStore == null) { 162 | throw new DbDetachedException(); 163 | } 164 | __boxStore.boxFor(UserBox.class).remove(this); 165 | } 166 | 167 | /** 168 | * Puts the entity in its object box. 169 | * Entity must attached to an entity context. 170 | */ 171 | @Generated(hash = 1264746468) 172 | public void put() { 173 | if (__boxStore == null) { 174 | throw new DbDetachedException(); 175 | } 176 | __boxStore.boxFor(UserBox.class).put(this); 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/orma/OrderOrma.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.orma; 2 | 3 | 4 | import android.support.annotation.Nullable; 5 | 6 | import com.github.gfx.android.orma.SingleAssociation; 7 | import com.github.gfx.android.orma.annotation.*; 8 | 9 | import java.util.Date; 10 | 11 | @Table 12 | public class OrderOrma { 13 | 14 | @PrimaryKey/*(autoincrement = true)*/ public long id; 15 | @Column public String title; 16 | @Column public String description; 17 | @Column public Date expiration; 18 | @Column public Date created; 19 | @Column public int count; 20 | @Column public double price; 21 | 22 | //@Column public long userId; 23 | @Nullable 24 | @Column(indexed = true) public SingleAssociation user; 25 | 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/orma/UserOrma.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.orma; 2 | 3 | import com.github.gfx.android.orma.annotation.*; 4 | 5 | @Table 6 | public class UserOrma { 7 | 8 | @PrimaryKey/*(autoincrement = true) */ public long id; 9 | @Column public String name; 10 | @Column public String login; 11 | @Column public String password; 12 | @Column public String description; 13 | @Column public String phone; 14 | @Column public String sex; 15 | @Column public int age; 16 | @Column public double height; 17 | 18 | public OrderOrma_Relation getOrders(OrmaDatabase orma) { 19 | return orma.relationOfOrderOrma().userEq(this); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/ormlite/OrderOrmLite.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.ormlite 2 | 3 | import com.j256.ormlite.field.DatabaseField 4 | import com.j256.ormlite.misc.BaseDaoEnabled 5 | import com.j256.ormlite.table.DatabaseTable 6 | import ds.dbtests.db.Order 7 | import ds.dbtests.db.User 8 | import java.util.* 9 | 10 | @DatabaseTable 11 | class OrderOrmLite : Order, BaseDaoEnabled() { 12 | 13 | @DatabaseField(generatedId = true) override var id: Long? = null 14 | @DatabaseField override var price: Double = 0.0 15 | @DatabaseField override var title: String? = null 16 | @DatabaseField(foreign = true, foreignAutoRefresh = false,index = true) private lateinit var _user: UserOrmLite 17 | @DatabaseField override var description: String? = null 18 | @DatabaseField override var expiration: Date? = null 19 | @DatabaseField override var created: Date? = null 20 | @DatabaseField override var count: Int = 0 21 | override var user: User? 22 | get() = _user 23 | set(v) { 24 | _user = v as UserOrmLite 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/ormlite/OrmLiteDB.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.ormlite 2 | 3 | import android.content.Context 4 | import android.database.sqlite.SQLiteDatabase 5 | import com.j256.ormlite.android.apptools.OpenHelperManager 6 | import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper 7 | import com.j256.ormlite.dao.BaseDaoImpl 8 | import com.j256.ormlite.dao.Dao 9 | import com.j256.ormlite.misc.BaseDaoEnabled 10 | import com.j256.ormlite.support.ConnectionSource 11 | import com.j256.ormlite.table.TableUtils 12 | import ds.dbtests.App 13 | 14 | private val DATABASE_NAME: String = "ormlite_db" 15 | private val DATABASE_VERSION: Int = 3 16 | 17 | class OrmLiteDB(context: Context?) 18 | : OrmLiteSqliteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { 19 | 20 | private var classes = arrayOf>>(UserOrmLite::class.java, OrderOrmLite::class.java) 21 | lateinit var usersDao: BaseDaoImpl 22 | lateinit var ordersDao: BaseDaoImpl 23 | 24 | init { 25 | usersDao = getDao(UserOrmLite::class.java) 26 | ordersDao = getDao(OrderOrmLite::class.java) 27 | } 28 | 29 | override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) { 30 | for (cls in classes) { 31 | TableUtils.createTable(connectionSource, cls) 32 | } 33 | } 34 | 35 | override fun , T> getDao(clazz: Class): D { 36 | val dao: D 37 | dao = super.getDao(clazz) 38 | dao.setObjectCache(true) 39 | return dao 40 | } 41 | 42 | override fun onUpgrade(database: SQLiteDatabase, connectionSource: ConnectionSource, oldVersion: Int, newVersion: Int) { 43 | for (cls in classes) { 44 | dropTable(connectionSource,cls) 45 | } 46 | // recreating tables 47 | onCreate(database, connectionSource) 48 | } 49 | 50 | fun dropTable(connectionSource: ConnectionSource, cls: Class) { 51 | TableUtils.dropTable(connectionSource, cls, true) 52 | } 53 | 54 | companion object{ 55 | val instance by lazy { OpenHelperManager.getHelper(App.instance, OrmLiteDB::class.java) } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/ormlite/UserOrmLite.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.ormlite 2 | 3 | import com.j256.ormlite.field.DatabaseField 4 | import com.j256.ormlite.field.ForeignCollectionField 5 | import com.j256.ormlite.misc.BaseDaoEnabled 6 | import com.j256.ormlite.table.DatabaseTable 7 | import ds.dbtests.db.Order 8 | import ds.dbtests.db.User 9 | 10 | @DatabaseTable 11 | class UserOrmLite : User, BaseDaoEnabled() { 12 | 13 | @DatabaseField(generatedId = true) override var id: Long? = null 14 | @DatabaseField override var age: Int = 0 15 | @DatabaseField override var name: String? = null 16 | @ForeignCollectionField(eager = false) private lateinit var _orders: java.util.Collection 17 | @DatabaseField override var login: String? = null 18 | @DatabaseField override var password: String? = null 19 | @DatabaseField override var description: String? = null 20 | @DatabaseField override var phone: String? = null 21 | @DatabaseField override var sex: String? = null 22 | @DatabaseField override var height: Double = 0.0 23 | override var orders: Collection 24 | get() = _orders as Collection 25 | set(v) { 26 | _orders = v as java.util.Collection 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/realm/OrderRealm.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.realm 2 | 3 | import ds.dbtests.db.Order 4 | import ds.dbtests.db.User 5 | import io.realm.RealmObject 6 | import io.realm.annotations.Ignore 7 | import io.realm.annotations.PrimaryKey 8 | import io.realm.annotations.RealmClass 9 | import java.util.* 10 | 11 | @RealmClass 12 | open class OrderRealm : RealmObject() { 13 | @PrimaryKey open var id: Long = -1 14 | open var title: String? = null 15 | open var description: String? = null 16 | open var expiration: Date? = null 17 | open var created: Date? = null 18 | open var count: Int = 0 19 | open var price: Double = 0.0 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/realm/UserRealm.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.realm 2 | 3 | import ds.dbtests.db.Order 4 | import ds.dbtests.db.User 5 | import io.realm.RealmList 6 | import io.realm.RealmObject 7 | import io.realm.annotations.Ignore 8 | import io.realm.annotations.PrimaryKey 9 | import io.realm.annotations.RealmClass 10 | 11 | @RealmClass 12 | open class UserRealm : RealmObject() { 13 | @PrimaryKey open var id: Long = -1 14 | open var name: String? = null 15 | open var login: String? = null 16 | open var password: String? = null 17 | open var description: String? = null 18 | open var phone: String? = null 19 | open var sex: String? = null 20 | open var age: Int = 0 21 | open var height: Double = 0.0 22 | open var orders: RealmList = RealmList() 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/requery/OrderRequery.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.requery; 2 | 3 | 4 | import java.util.Date; 5 | 6 | import io.requery.*; 7 | 8 | @Entity 9 | public class OrderRequery { 10 | 11 | @Key 12 | @Generated 13 | public long id; 14 | public String title; 15 | public String description; 16 | public Date expiration; 17 | public Date created; 18 | public int count; 19 | public double price; 20 | 21 | @ManyToOne(cascade = {}) 22 | //@Index 23 | //@Transient 24 | public UserRequery user; 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/requery/RequeryTest.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.requery 2 | 3 | import android.content.Context 4 | import ds.dbtests.TestBase 5 | 6 | class RequeryTest (val ctx: Context): TestBase() { 7 | 8 | override fun init() { 9 | 10 | } 11 | 12 | override fun writeTest() { 13 | 14 | } 15 | 16 | override fun readTest(lazy: Boolean) { 17 | 18 | } 19 | 20 | override fun clean() { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/requery/UserRequery.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.requery; 2 | 3 | 4 | import java.util.List; 5 | 6 | import io.requery.*; 7 | 8 | @Entity 9 | public class UserRequery { 10 | 11 | @Key 12 | @Generated 13 | public long id; 14 | public String name; 15 | public String login; 16 | public String password; 17 | public String description; 18 | public String phone; 19 | public String sex; 20 | public int age; 21 | public double height; 22 | 23 | @OneToMany(cascade = {}) 24 | //@Transient 25 | public List orders; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/AppDatabase.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | import android.arch.persistence.room.Database; 4 | import android.arch.persistence.room.RoomDatabase; 5 | import android.arch.persistence.room.TypeConverters; 6 | 7 | @Database(entities = {UserRoom.class, OrderRoom.class}, version = 1) 8 | @TypeConverters(Converters.class) 9 | public abstract class AppDatabase extends RoomDatabase { 10 | public abstract UserDao userDao(); 11 | 12 | public abstract OrderDao orderDao(); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/Converters.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | import android.arch.persistence.room.TypeConverter; 4 | 5 | import java.util.Date; 6 | 7 | public class Converters { 8 | @TypeConverter 9 | public static Date fromTimestamp(Long value) { 10 | return value == null ? null : new Date(value); 11 | } 12 | 13 | @TypeConverter 14 | public static Long dateToTimestamp(Date date) { 15 | return date == null ? null : date.getTime(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/OrderDao.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | import android.arch.persistence.room.Dao; 4 | import android.arch.persistence.room.Insert; 5 | import android.arch.persistence.room.Query; 6 | 7 | import java.util.List; 8 | 9 | @Dao 10 | public interface OrderDao { 11 | 12 | @Insert 13 | void insert(List orders); 14 | 15 | @Insert 16 | void insert(OrderRoom order); 17 | 18 | @Query("delete from OrderRoom") 19 | void deleteAll(); 20 | 21 | @Query("select * from OrderRoom") 22 | List fetchAll(); 23 | 24 | @Query("select * from OrderRoom where userId=:userId") 25 | List fetchOrders(long userId); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/OrderRoom.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | 4 | import android.arch.persistence.room.Entity; 5 | import android.arch.persistence.room.ForeignKey; 6 | import android.arch.persistence.room.PrimaryKey; 7 | 8 | import java.util.Date; 9 | 10 | @Entity(foreignKeys = @ForeignKey( 11 | entity = UserRoom.class, 12 | childColumns = "userId", 13 | parentColumns = "id" 14 | 15 | )) 16 | public class OrderRoom { 17 | 18 | @PrimaryKey(autoGenerate = true) 19 | public long id; 20 | public String title; 21 | public String description; 22 | public Date expiration; 23 | public Date created; 24 | public int count; 25 | public double price; 26 | 27 | public long userId; 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/UserDao.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | import android.arch.persistence.room.Dao; 4 | import android.arch.persistence.room.Insert; 5 | import android.arch.persistence.room.Query; 6 | 7 | import java.util.List; 8 | 9 | @Dao 10 | public interface UserDao { 11 | 12 | @Insert 13 | List insert(List users); 14 | 15 | @Insert 16 | long insert(UserRoom user); 17 | 18 | @Query("delete from UserRoom") 19 | void deleteAll(); 20 | 21 | @Query("select * from UserRoom") 22 | List fetchAll(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/room/UserRoom.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.room; 2 | 3 | 4 | import android.arch.persistence.room.Entity; 5 | import android.arch.persistence.room.PrimaryKey; 6 | 7 | @Entity 8 | public class UserRoom { 9 | 10 | @PrimaryKey(autoGenerate = true) 11 | public long id; 12 | public String name; 13 | public String login; 14 | public String password; 15 | public String description; 16 | public String phone; 17 | public String sex; 18 | public int age; 19 | public double height; 20 | 21 | //@Relation(parentColumn = "id", entityColumn = "userId") 22 | //public List orders; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/snappydb/OrderSnappy.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.snappydb 2 | 3 | import ds.dbtests.db.Order 4 | import ds.dbtests.db.User 5 | import java.util.* 6 | 7 | class OrderSnappy : Order { 8 | override var id: Long? = null 9 | override var title: String? = null 10 | override var description: String? = null 11 | override var expiration: Date? = null 12 | override var created: Date? = null 13 | override var count: Int = 0 14 | override var price: Double = 0.0 15 | override var user: User? 16 | get() = userSnappy 17 | set(v) { 18 | userSnappy = v as UserSnappy 19 | } 20 | 21 | private lateinit var userSnappy: UserSnappy 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/ds/dbtests/db/snappydb/UserSnappy.kt: -------------------------------------------------------------------------------- 1 | package ds.dbtests.db.snappydb 2 | 3 | import ds.dbtests.db.Order 4 | import ds.dbtests.db.User 5 | 6 | class UserSnappy : User { 7 | 8 | override var id: Long? = null 9 | override var name: String? = null 10 | override var login: String? = null 11 | override var password: String? = null 12 | override var description: String? = null 13 | override var phone: String? = null 14 | override var sex: String? = null 15 | override var age: Int = 0 16 | override var height: Double = 0.0 17 | override var orders: Collection 18 | get() = ordersSnappy 19 | set(v) { 20 | ordersSnappy = v as MutableList 21 | } 22 | 23 | 24 | private var ordersSnappy: MutableList = arrayListOf() 25 | 26 | fun addOrder(o: OrderSnappy){ 27 | ordersSnappy.add(o) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_chart.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | #be3a3a 8 | #2ba95d 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ORM Benchmarks 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/ds/dbtests/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package ds.dbtests; 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 | 12 | @Test 13 | public void addition_isCorrect() throws Exception { 14 | assertEquals(4, 2 + 2); 15 | } 16 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlinVersion = '1.2.10' 3 | 4 | repositories { 5 | jcenter() 6 | google() 7 | maven { url "http://objectbox.net/beta-repo/" } 8 | 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.0.1' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 13 | classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1' 14 | classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' 15 | classpath "io.realm:realm-gradle-plugin:3.1.1" 16 | classpath 'com.google.gms:google-services:3.1.1' 17 | classpath 'io.objectbox:objectbox-gradle-plugin:0.9.9' 18 | 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | jcenter() 25 | google() 26 | maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' } 27 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } 28 | maven { url 'https://github.com/uPhyca/stetho-realm/raw/master/maven-repo' } 29 | maven { url "https://jitpack.io" } 30 | maven { url "http://objectbox.net/beta-repo/" } 31 | } 32 | } 33 | 34 | task clean(type: Delete) { 35 | delete rootProject.buildDir 36 | } 37 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jan 08 12:56:09 EET 2018 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-4.4-bin.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 | -------------------------------------------------------------------------------- /pics/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mykola-dev/Android-ORM-Benchmarks/d28c5a0cab19a0fc8b5f18f5346aee0c075cd199/pics/screenshot.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------