需要 NoSQL Android 缓存
Need for NoSQL Android Cache
我 运行 几个基于 MongoDb 的 API 使用 Spring 数据
实现
我的问题是有一个 Android 可以无缝处理文档的缓存数据库,尤其是带有嵌入式文档的文档!
MongoDb 似乎有解决方案(MongoDb 领域)但它已连接到付费托管数据库
作为从 API 调用后端接收到 JSON 假数据的示例可能如下所示
{
"detail": "Page 1 of 1",
"count": 1,
"page": 1,
"results": [
{
"prospectId": "5cb2e9424274072ec4bb419c",
"name": "Bill",
"lastName": "Gates",
"phone": "0108101081",
"email": "gates.william@gmail.com",
"company": {
"companyId": "60847dc8ba7e6a4ae0fa5f93",
"name": "Microsoft",
"email": "info@Microsoft.com",
"address": {
"addressId": "5cb2e9424274072ec4bb4199",
"label": "Home",
"number": "1",
"street": "Microsoft Way",
"timestamp": 1631087921460
},
"timestamp": 1631087921855
},
"address": {
"addressId": "5cb2e9424274072ec4bb4199",
"label": "Home",
"number": "1",
"street": "Microsoft Way",
"timestamp": 1631087921460
},
"timestamp": 1631087922537
}
]
}
前景Class
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
@DBRef
var company: Company? = null
@DBRef
var address: Address? = null
var timestamp: Long = nowToLongUTC()
}
我的公司
class Company {
@Id
var companyId: String? = null
var name: String? = null
var email: String? = null
@DBRef
var address: Address? = null
var timestamp: Long? = null
}
我的地址
class Address {
@Id
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = nowToLongUTC()
}
它由包含 @dbRef Company
和 @dbRef Address
的 类 生成
公司还包括 @dbRef Address
潜在客户和公司都包含一个地址,结合它具有文档结构中的文档
在noSql类型的文档中是相当自然的参考文档
我需要一个理解 noSql (MongoDb) 的 Android 缓存,并且可以本地处理嵌入在文档中嵌入的文档,
房间银河系失败!作为一个 SQL 并且做得不好。使用 room 的 @Embedded
表示法有助于嵌入文档的一个级别,但下一个级别需要使用 TypeConverter。这就是 SQL 让我失望的原因。
Room fails galactically! being a SQL and suffers doing it properly. Using room's @Embedded notation helps for one level of embedded document but the next level need to be using a TypeConverter. That is how SQL fails me.
也许以下是您根据“假”数据寻找的内容。这忽略了@DBRef,而是有实体(tables)地址、公司和前景,并有支持性的 POJO 的 CompanyWithAddress 和(为了更好的名字)ProspectWithCompanyWithAddressAndWithProspectAddress,这些使用@Relation 嵌入底层各自的实体子对象。
所以实体是:-
地址
@Entity /* This indicates that this is a table */
class Address {
//@Id
@PrimaryKey /* Room requires a Primary Key for a table */
var addressId: String = ""
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = /* nowToLongUTC() */ System.currentTimeMillis() /* used for convenience */
}
公司
@Entity(
foreignKeys = [
ForeignKey(
entity = Address::class,
parentColumns = ["addressId"],
childColumns = ["addressRef"],
/* You may or may not want onDelete and onUpdate actions */
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
/* you may wish to refer to https://sqlite.org/foreignkeys.html */
)
],
indices = [
Index("addressRef") /* Room will warn if a FK column is not indexed */
]
)
class Company {
//@Id
@PrimaryKey
var companyId: String = ""
var name: String? = null
var email: String? = null
//@DBRef
//var address: Address? = null
// Rather than de-normalise DB, waste space,
// here we reference the address rather than include the address
// the Foreign Key above adds a rule saying that the value of addressRef
// MUST be a value that is in an addressId column in the address table
// Foreign Keys are optional but recommended to enforce referential integrity
// break the rule and an error occurs
var addressRef: String? = null
var timestamp: Long? = null
}
和前景
@Entity(
foreignKeys = [
ForeignKey(
entity = Company::class,
parentColumns = ["companyId"],
childColumns = ["companyRef"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = Address::class,
parentColumns = ["addressId"],
childColumns = ["prospectAddressRef"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
],
indices = [
Index("companyRef"),
Index("prospectAddressRef")
]
)
class Prospect {
//@Id
@PrimaryKey
var prospectId: String = ""
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
//@DBRef
var companyRef: String? = null
//@DBRef
@ColumnInfo(name = "prospectAddressRef") /* defines the column name in the table to avoid ambiguities */
var addressRef: String? = null
var timestamp: Long = /* nowToLongUTC() */ System.currentTimeMillis()
}
POJO 的 :-
公司地址
class CompanyWithAddress {
@Embedded
var company: Company? = null
@Relation(
entity = Address::class,
parentColumn = "addressRef",
entityColumn = "addressId"
)
var address: Address? = null
}
- 所以一家有地址的公司注意到 Address 对象是通过包含 相关 地址的 addressId 的 addressRef 获得的(不需要 TypeConverter)
和ProspectWithCompanyWithAddressAndWithProspectAddress
class ProspectWithCompanyWithAddressAndWithProspectAddress {
@Embedded
var prospect: Prospect? = null
@Relation(
entity = Company::class,
parentColumn = "companyRef",
entityColumn = "companyId"
)
var companyWithAddress: CompanyWithAddress? = null
@Relation(
entity = Address::class,
parentColumn = "prospectAddressRef",
entityColumn = "addressId"
)
var address: Address? = null
}
Dao 在名为 AllDao
的 class 中用于上述演示
@Dao
abstract class AllDao {
@Insert
abstract fun insert(address: Address): Long
@Insert
abstract fun insert(company: Company): Long
@Insert
abstract fun insert(prospect: Prospect): Long
@Transaction
@Query("SELECT * FROM prospect")
abstract fun getALlFullProspects(): List<ProspectWithCompanyWithAddressAndWithProspectAddress>
}
- 这些允许插入相应的 tables
- 请注意,由于外键,必须在使用该地址的公司和潜在客户之前插入地址,并且必须在插入潜在客户之前插入公司。
- 使用外键(可选)没关系。
一个非常基本的@Database TheDatabase
@Database(
entities = [Address::class,Company::class,Prospect::class],
version = 1
)
abstract class TheDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDao
companion object {
@Volatile
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase::class.java,
"thedatabase.db"
)
.allowMainThreadQueries() /* for convenience/brevity of demo */
.build()
}
return instance as TheDatabase
}
}
}
将它们放在一个 Activity 中(运行 在 brevity/convenience 的主线程上) MainActivity : -
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val a1Id = "5cb2e9424274072ec4bb4199"
val c1Id = "60847dc8ba7e6a4ae0fa5f93"
val p1Id = "5cb2e9424274072ec4bb419c"
var a1 = Address()
a1.addressId = a1Id
a1.label = "Home"
a1.number = "1"
a1.street = "MS Way"
dao.insert(a1)
var c1 = Company()
c1.companyId = c1Id
c1.email = "info@Microsoft.com"
c1.name = "Microsoft"
c1.addressRef = a1Id
dao.insert(c1)
var p1 = Prospect()
p1.prospectId = p1Id
p1.name = "Bill"
p1.lastName = "Gates"
p1.email = "gates.william@gmail.com"
p1.phone = "0108101081"
p1.companyRef = c1Id
p1.addressRef = a1Id
dao.insert(p1)
/* Going to add a 2nd Prospect with a 2nd Company with separate addresses */
val a2Id = "6cb2e9424274072ec4bb4199"
val a3Id = "7cb2e9424274072ec4bb4199"
val c2Id = "70847dc8ba7e6a4ae0fa5f93"
val p2Id = "6cb2e9424274072ec4bb419c"
/* change the initial address ready for the insert of the 2nd*/
a1.addressId = a2Id
a1.street = "Apple lane"
a1.number = "33"
a1.label = "Work"
dao.insert(a1)
/* change the 2nd address ready for the insert of the 3rd */
a1.addressId = a3Id
a1.label = "Holiday"
a1.number = "111"
a1.street = "Lazy Street"
dao.insert(a1)
/* Change the company and insert a new one */
c1.companyId = c2Id
c1.name = "Apple Inc"
c1.email = "info@apple.inc"
c1.addressRef = a2Id
dao.insert(c1)
/* Change the prospect and insert a new one */
p1.addressRef = a3Id
p1.companyRef = c2Id
p1.prospectId = p2Id
dao.insert(p1)
/* Now the data has been added extract it and output the extracted to the log*/
var TAG = "PROSPECTINFO"
for(p: ProspectWithCompanyWithAddressAndWithProspectAddress in dao.getALlFullProspects()) {
Log.d(TAG,
"Prospect: Name = ${p.prospect!!.name}, ${p.prospect!!.lastName} Phone is ${p.prospect!!.phone}" +
"\n\tCompany is ${p.companyWithAddress!!.company!!.name} " +
"\n\t\tCompany Address is ${p.companyWithAddress!!.address!!.number} ${p.companyWithAddress!!.address!!.street}" +
"\n\tProspect Address is ${p.address!!.number} ${p!!.address!!.street}"
)
}
}
}
结果
上面是运行时的日志(设计成只运行一次,运行第二次会出现UNIQIUE冲突):-
D/PROSPECTINFO: Prospect: Name = Bill, Gates Phone is 0108101081
Company is Microsoft
Company Address is 1 MS Way
Prospect Address is 1 MS Way
D/PROSPECTINFO: Prospect: Name = Bill, Gates Phone is 0108101081
Company is Apple Inc
Company Address is 33 Apple lane
Prospect Address is 111 Lazy Street
通过 App Inspector,数据库是:-
地址 table :-
公司table:-
- 时间戳为 NULL,因为它们未设置(根据您的原始代码)
前景 table :-
- Name/Last 名称等是相同的值,因为这些没有改变。重要的是,虽然 companyRef 和 prospectAddressRef 值引用各自的 companies/addresses.
你可以看看亚硝酸盐数据库here。 Nitrite 是一个用 Java 编写的开源 nosql 嵌入式文档存储,非常适合 Android 或 Java 桌面应用程序。幸运的是,它支持 mongodb,例如 api。
在您的特定用例中,这里有两个选项。
- 您删除
@DBRef
注释(nitrite 不支持数据库引用)并将 Prospect
对象及其所有嵌入对象插入到 nitrite 对象存储库中。
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
var company: Company? = null
var address: Address? = null
var timestamp: Long = System.currentTimeMillis()
}
class Company {
var companyId: String? = null
var name: String? = null
var email: String? = null
var address: Address? = null
var timestamp: Long? = null
}
class Address {
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = System.currentTimeMillis()
}
val db = nitrite {
file = File(fileName)
autoCommitBufferSize = 2048
compress = true
autoCompact = false
}
// create repository
val prospects = db.getRepository<Prospect>()
// create/get your object
val obj = Prospect()
...
// insert the object into the database
prospects.insert(obj)
// retrieve like
val cursor = prospects.find(Prospect::prospectId eq "xyz")
// or
val cursor = prospects.find("prospectId.company.address.number" eq 123)
- 您分别为
Prospects
、Company
和 Address
创建了 3 个对象存储库,并将 ID 存储在引用位置。但是你必须调用适当的对象存储库来获取实际的对象。
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
var companyId: String? = null
var addressId: String? = null
var timestamp: Long = System.currentTimeMillis()
}
class Company {
@Id
var companyId: String? = null
var name: String? = null
var email: String? = null
var addressId: String? = null
var timestamp: Long? = null
}
class Address {
@Id
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = System.currentTimeMillis()
}
val db = nitrite {
file = File(fileName)
autoCommitBufferSize = 2048
compress = true
autoCompact = false
}
// create repositories
val prospects = db.getRepository<Prospect>()
val companies = db.getRepository<Company>()
val addresses = db.getRepository<Address>()
// create/get your objects
val pObj = Prospect()
val cObj = Company()
val aObj = Address()
...
// insert the object into the database
prospects.insert(pObj)
companies.insert(cObj)
addresses.insert(aObj)
// retrieve like
val p = prospects.find(Prospect::prospectId eq "xyz").firstOrNull()
val a = addresses.find(Address::addressId eq p.addressId)
这里是完整的documentation帮助你,如果你被卡住了。我建议您使用 3.4.2 版,因为它已准备就绪且稳定。
免责声明:我是 Nitrite 数据库的开发者。
我 运行 几个基于 MongoDb 的 API 使用 Spring 数据
实现我的问题是有一个 Android 可以无缝处理文档的缓存数据库,尤其是带有嵌入式文档的文档!
MongoDb 似乎有解决方案(MongoDb 领域)但它已连接到付费托管数据库
作为从 API 调用后端接收到 JSON 假数据的示例可能如下所示
{
"detail": "Page 1 of 1",
"count": 1,
"page": 1,
"results": [
{
"prospectId": "5cb2e9424274072ec4bb419c",
"name": "Bill",
"lastName": "Gates",
"phone": "0108101081",
"email": "gates.william@gmail.com",
"company": {
"companyId": "60847dc8ba7e6a4ae0fa5f93",
"name": "Microsoft",
"email": "info@Microsoft.com",
"address": {
"addressId": "5cb2e9424274072ec4bb4199",
"label": "Home",
"number": "1",
"street": "Microsoft Way",
"timestamp": 1631087921460
},
"timestamp": 1631087921855
},
"address": {
"addressId": "5cb2e9424274072ec4bb4199",
"label": "Home",
"number": "1",
"street": "Microsoft Way",
"timestamp": 1631087921460
},
"timestamp": 1631087922537
}
]
}
前景Class
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
@DBRef
var company: Company? = null
@DBRef
var address: Address? = null
var timestamp: Long = nowToLongUTC()
}
我的公司
class Company {
@Id
var companyId: String? = null
var name: String? = null
var email: String? = null
@DBRef
var address: Address? = null
var timestamp: Long? = null
}
我的地址
class Address {
@Id
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = nowToLongUTC()
}
它由包含 @dbRef Company
和 @dbRef Address
的 类 生成
公司还包括 @dbRef Address
潜在客户和公司都包含一个地址,结合它具有文档结构中的文档
在noSql类型的文档中是相当自然的参考文档
我需要一个理解 noSql (MongoDb) 的 Android 缓存,并且可以本地处理嵌入在文档中嵌入的文档,
房间银河系失败!作为一个 SQL 并且做得不好。使用 room 的 @Embedded
表示法有助于嵌入文档的一个级别,但下一个级别需要使用 TypeConverter。这就是 SQL 让我失望的原因。
Room fails galactically! being a SQL and suffers doing it properly. Using room's @Embedded notation helps for one level of embedded document but the next level need to be using a TypeConverter. That is how SQL fails me.
也许以下是您根据“假”数据寻找的内容。这忽略了@DBRef,而是有实体(tables)地址、公司和前景,并有支持性的 POJO 的 CompanyWithAddress 和(为了更好的名字)ProspectWithCompanyWithAddressAndWithProspectAddress,这些使用@Relation 嵌入底层各自的实体子对象。
所以实体是:-
地址
@Entity /* This indicates that this is a table */
class Address {
//@Id
@PrimaryKey /* Room requires a Primary Key for a table */
var addressId: String = ""
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = /* nowToLongUTC() */ System.currentTimeMillis() /* used for convenience */
}
公司
@Entity(
foreignKeys = [
ForeignKey(
entity = Address::class,
parentColumns = ["addressId"],
childColumns = ["addressRef"],
/* You may or may not want onDelete and onUpdate actions */
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
/* you may wish to refer to https://sqlite.org/foreignkeys.html */
)
],
indices = [
Index("addressRef") /* Room will warn if a FK column is not indexed */
]
)
class Company {
//@Id
@PrimaryKey
var companyId: String = ""
var name: String? = null
var email: String? = null
//@DBRef
//var address: Address? = null
// Rather than de-normalise DB, waste space,
// here we reference the address rather than include the address
// the Foreign Key above adds a rule saying that the value of addressRef
// MUST be a value that is in an addressId column in the address table
// Foreign Keys are optional but recommended to enforce referential integrity
// break the rule and an error occurs
var addressRef: String? = null
var timestamp: Long? = null
}
和前景
@Entity(
foreignKeys = [
ForeignKey(
entity = Company::class,
parentColumns = ["companyId"],
childColumns = ["companyRef"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = Address::class,
parentColumns = ["addressId"],
childColumns = ["prospectAddressRef"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
],
indices = [
Index("companyRef"),
Index("prospectAddressRef")
]
)
class Prospect {
//@Id
@PrimaryKey
var prospectId: String = ""
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
//@DBRef
var companyRef: String? = null
//@DBRef
@ColumnInfo(name = "prospectAddressRef") /* defines the column name in the table to avoid ambiguities */
var addressRef: String? = null
var timestamp: Long = /* nowToLongUTC() */ System.currentTimeMillis()
}
POJO 的 :-
公司地址
class CompanyWithAddress {
@Embedded
var company: Company? = null
@Relation(
entity = Address::class,
parentColumn = "addressRef",
entityColumn = "addressId"
)
var address: Address? = null
}
- 所以一家有地址的公司注意到 Address 对象是通过包含 相关 地址的 addressId 的 addressRef 获得的(不需要 TypeConverter)
和ProspectWithCompanyWithAddressAndWithProspectAddress
class ProspectWithCompanyWithAddressAndWithProspectAddress {
@Embedded
var prospect: Prospect? = null
@Relation(
entity = Company::class,
parentColumn = "companyRef",
entityColumn = "companyId"
)
var companyWithAddress: CompanyWithAddress? = null
@Relation(
entity = Address::class,
parentColumn = "prospectAddressRef",
entityColumn = "addressId"
)
var address: Address? = null
}
Dao 在名为 AllDao
的 class 中用于上述演示@Dao
abstract class AllDao {
@Insert
abstract fun insert(address: Address): Long
@Insert
abstract fun insert(company: Company): Long
@Insert
abstract fun insert(prospect: Prospect): Long
@Transaction
@Query("SELECT * FROM prospect")
abstract fun getALlFullProspects(): List<ProspectWithCompanyWithAddressAndWithProspectAddress>
}
- 这些允许插入相应的 tables
- 请注意,由于外键,必须在使用该地址的公司和潜在客户之前插入地址,并且必须在插入潜在客户之前插入公司。
- 使用外键(可选)没关系。
一个非常基本的@Database TheDatabase
@Database(
entities = [Address::class,Company::class,Prospect::class],
version = 1
)
abstract class TheDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDao
companion object {
@Volatile
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase::class.java,
"thedatabase.db"
)
.allowMainThreadQueries() /* for convenience/brevity of demo */
.build()
}
return instance as TheDatabase
}
}
}
将它们放在一个 Activity 中(运行 在 brevity/convenience 的主线程上) MainActivity : -
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val a1Id = "5cb2e9424274072ec4bb4199"
val c1Id = "60847dc8ba7e6a4ae0fa5f93"
val p1Id = "5cb2e9424274072ec4bb419c"
var a1 = Address()
a1.addressId = a1Id
a1.label = "Home"
a1.number = "1"
a1.street = "MS Way"
dao.insert(a1)
var c1 = Company()
c1.companyId = c1Id
c1.email = "info@Microsoft.com"
c1.name = "Microsoft"
c1.addressRef = a1Id
dao.insert(c1)
var p1 = Prospect()
p1.prospectId = p1Id
p1.name = "Bill"
p1.lastName = "Gates"
p1.email = "gates.william@gmail.com"
p1.phone = "0108101081"
p1.companyRef = c1Id
p1.addressRef = a1Id
dao.insert(p1)
/* Going to add a 2nd Prospect with a 2nd Company with separate addresses */
val a2Id = "6cb2e9424274072ec4bb4199"
val a3Id = "7cb2e9424274072ec4bb4199"
val c2Id = "70847dc8ba7e6a4ae0fa5f93"
val p2Id = "6cb2e9424274072ec4bb419c"
/* change the initial address ready for the insert of the 2nd*/
a1.addressId = a2Id
a1.street = "Apple lane"
a1.number = "33"
a1.label = "Work"
dao.insert(a1)
/* change the 2nd address ready for the insert of the 3rd */
a1.addressId = a3Id
a1.label = "Holiday"
a1.number = "111"
a1.street = "Lazy Street"
dao.insert(a1)
/* Change the company and insert a new one */
c1.companyId = c2Id
c1.name = "Apple Inc"
c1.email = "info@apple.inc"
c1.addressRef = a2Id
dao.insert(c1)
/* Change the prospect and insert a new one */
p1.addressRef = a3Id
p1.companyRef = c2Id
p1.prospectId = p2Id
dao.insert(p1)
/* Now the data has been added extract it and output the extracted to the log*/
var TAG = "PROSPECTINFO"
for(p: ProspectWithCompanyWithAddressAndWithProspectAddress in dao.getALlFullProspects()) {
Log.d(TAG,
"Prospect: Name = ${p.prospect!!.name}, ${p.prospect!!.lastName} Phone is ${p.prospect!!.phone}" +
"\n\tCompany is ${p.companyWithAddress!!.company!!.name} " +
"\n\t\tCompany Address is ${p.companyWithAddress!!.address!!.number} ${p.companyWithAddress!!.address!!.street}" +
"\n\tProspect Address is ${p.address!!.number} ${p!!.address!!.street}"
)
}
}
}
结果
上面是运行时的日志(设计成只运行一次,运行第二次会出现UNIQIUE冲突):-
D/PROSPECTINFO: Prospect: Name = Bill, Gates Phone is 0108101081
Company is Microsoft
Company Address is 1 MS Way
Prospect Address is 1 MS Way
D/PROSPECTINFO: Prospect: Name = Bill, Gates Phone is 0108101081
Company is Apple Inc
Company Address is 33 Apple lane
Prospect Address is 111 Lazy Street
通过 App Inspector,数据库是:-
地址 table :-
公司table:-
- 时间戳为 NULL,因为它们未设置(根据您的原始代码)
前景 table :-
- Name/Last 名称等是相同的值,因为这些没有改变。重要的是,虽然 companyRef 和 prospectAddressRef 值引用各自的 companies/addresses.
你可以看看亚硝酸盐数据库here。 Nitrite 是一个用 Java 编写的开源 nosql 嵌入式文档存储,非常适合 Android 或 Java 桌面应用程序。幸运的是,它支持 mongodb,例如 api。
在您的特定用例中,这里有两个选项。
- 您删除
@DBRef
注释(nitrite 不支持数据库引用)并将Prospect
对象及其所有嵌入对象插入到 nitrite 对象存储库中。
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
var company: Company? = null
var address: Address? = null
var timestamp: Long = System.currentTimeMillis()
}
class Company {
var companyId: String? = null
var name: String? = null
var email: String? = null
var address: Address? = null
var timestamp: Long? = null
}
class Address {
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = System.currentTimeMillis()
}
val db = nitrite {
file = File(fileName)
autoCommitBufferSize = 2048
compress = true
autoCompact = false
}
// create repository
val prospects = db.getRepository<Prospect>()
// create/get your object
val obj = Prospect()
...
// insert the object into the database
prospects.insert(obj)
// retrieve like
val cursor = prospects.find(Prospect::prospectId eq "xyz")
// or
val cursor = prospects.find("prospectId.company.address.number" eq 123)
- 您分别为
Prospects
、Company
和Address
创建了 3 个对象存储库,并将 ID 存储在引用位置。但是你必须调用适当的对象存储库来获取实际的对象。
class Prospect {
@Id
var prospectId: String? = null
var name: String? = null
var lastName: String? = null
var phone: String? = null
var email: String? = null
var companyId: String? = null
var addressId: String? = null
var timestamp: Long = System.currentTimeMillis()
}
class Company {
@Id
var companyId: String? = null
var name: String? = null
var email: String? = null
var addressId: String? = null
var timestamp: Long? = null
}
class Address {
@Id
var addressId: String? = null
var label: String? = null
var number: String? = null
var street: String? = null
var timestamp: Long = System.currentTimeMillis()
}
val db = nitrite {
file = File(fileName)
autoCommitBufferSize = 2048
compress = true
autoCompact = false
}
// create repositories
val prospects = db.getRepository<Prospect>()
val companies = db.getRepository<Company>()
val addresses = db.getRepository<Address>()
// create/get your objects
val pObj = Prospect()
val cObj = Company()
val aObj = Address()
...
// insert the object into the database
prospects.insert(pObj)
companies.insert(cObj)
addresses.insert(aObj)
// retrieve like
val p = prospects.find(Prospect::prospectId eq "xyz").firstOrNull()
val a = addresses.find(Address::addressId eq p.addressId)
这里是完整的documentation帮助你,如果你被卡住了。我建议您使用 3.4.2 版,因为它已准备就绪且稳定。
免责声明:我是 Nitrite 数据库的开发者。