我尝试重构一些代码并移动几个架构以使用架构组件中的Room数据库。
我有这样的对象,我经常使用它从缓存中获取它。 这就是它的样子:
public class LocationEvents {
private Map<NexoIdentifier, Date> mDeviceFirstSeenDates;
private ArrayDeque<LocationGeoEvent> mGeoEvents;
private ArrayDeque<LocationRSSIEvent> mRSSIEvents;
private Map<NexoIdentifier, ScoredLocationEvent> mHighestScores;
///Some methods
}
我想用这种结构建模数据库。 因此会有像LocationGeoEvent,LocationRSSIEvent,ScoredLocationEvent这样的实体。
他们看起来像这样:
public class LocationGeoEvent {
private double mLongitude;
private double mLatitude;
private double mAccuracy;
private Date mTimestamp;
}
public class LocationRSSIEvent {
private int mRSSI;
private NexoIdentifier mNexoIdentifier;
private Date mTimestamp;
}
public class ScoredLocationEvent {
private float mScore;
private NexoIdentifier mNexoIdentifier;
private LocationRSSIEvent mLocationRSSIEvent;
private LocationGeoEvent mLocationGeoEvent;
private Date mScoreCalculatedTime;
private boolean mSent;
private boolean mPreviousSent;
}
NexoIdentifier是一个简单的POJO:
class NexoIdentifier {
abstract val partialSerialID: String
abstract val id: String
abstract val countryAndManufacturer: String
}
那我如何利用房间建立关系呢?甚至可以将LocationEvent实体设为一次吗?因此,例如,我希望能够使用嵌套在其中的所有列表来获取LocationEvent。或者也许有另一种方法可以做到这一点? 还不知道如何在LocationEvents - DeviceFirstSeenDates和HighestScores中对这两个地图进行建模 - 作为两个与其他实体相关的独立实体?但到底怎么样?我会非常感谢这个例子中的帮助,我真的被困了
更新
@Entity(tableName = "location_events")
data class LocationEvents(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded(prefix = "device") val mDeviceFirstSeenDates: Map<NexoIdentifier, Date> = HashMap(),
@Embedded(prefix = "events") val mGeoEvents: ArrayDeque<LocationGeoEvent> = ArrayDeque(),
val mRSSIEvents: ArrayDeque<LocationRSSIEvent> = ArrayDeque(),
val mHighestScores: Map<NexoIdentifier, ScoredLocationEvent> = HashMap()
) {
constructor() : this(0L, hashMapOf<NexoIdentifier, Date>(),
ArrayDeque(), ArrayDeque(), hashMapOf<NexoIdentifier, ScoredLocationEvent>()
)
}
错误:错误:实体和Pojos必须具有可用的公共构造函数。您可以拥有一个空构造函数或其参数与字段匹配的构造函数(按名称和类型)。
答案 0 :(得分:4)
您可以使用Embedded。如果您使用相同的变量名称,则需要使用前缀。
示例:
public class LocationEvents {
@Embedded(prefix="device") private Map<NexoIdentifier, Date> mDeviceFirstSeenDates;
@Embedded(prefix="events") private ArrayDeque<LocationGeoEvent> mGeoEvents;
private ArrayDeque<LocationRSSIEvent> mRSSIEvents;
private Map<NexoIdentifier, ScoredLocationEvent> mHighestScores;
}
或者你为此写了一个转换器。
示例:
public class DBConverters {
@TypeConverter
public static mapToString(Map<NexoIdentifier, Date value) {
return value == null ? null : Gson.toJson(value);
}
@TypeConverter
public static Map<NexoIdentifier, Date> fromMap(String value) {
return value == null ? null : Gson.fromJson(value, ...);
}
}
在数据库类中注释您的Converter
@TypeConverters(DBConverters::class)
abstract class YourDb : RoomDatabase() { }
更新(代码更新后):
警告意味着您至少需要一个可用的构造函数。要解决这个问题并仍然允许“数据”类,您需要使用忽略注释并注意您没有任何可以为空的值。
@Ignore constructor() : this(0L, hashMapOf<NexoIdentifier, Date>(),
ArrayDeque(), ArrayDeque(), hashMapOf<NexoIdentifier, ScoredLocationEvent>()
这将确保Room使用您班级标题中使用的构造函数。
房间本身没有“真实”relationships,但你可以创建一个“虚拟类”来保存关系。 Room支持ForeignKey,它允许您在关系被更新或删除时定义行为。请注意,您只能将嵌入式用于其他类。如果有像HashMap这样的未知类型,你会写一个转换器。