我想创建一个如下所示的数据库。我阅读了文档,但没有找到任何类似的例子。你能帮助我吗?有几天,在这几天内,每天将有多顿饭和每天的地下水位
一旦应用程序启动,就会创建一个日期数据库,然后无论它在哪一天(可以手动更改日期),都会将每日水和每日膳食添加到那一天
"days":
[
{
"id": "Integer",
"date": "String",
"weight": "Float",
"height": "Integer",
"waist_circumference": "Integer",
"neck_circumference": "Integer",
"hip_circumference": "Integer",
"steps": "Long",
"taken_kcal": "Float",
"burned_kcal": "Float",
"carb": "Float",
"protein": "Float",
"fat": "Float",
"water_ml": "Integer",
"water_percent": "Float",
"meals":
[
{
"day_id": "Integer",
"id": "Integer",
"food_meal_time": "String",
"food_name": "String",
"food_image": "String",
"food_kcal": "Float",
"food_portion": "String",
"food_carb": "Float",
"food_protein": "Float",
"food_fat": "Float"
},
{
"day_id": "Integer",
"id": "Integer",
"food_meal_time": "String",
"food_name": "String",
"food_image": "String",
"food_kcal": "Float",
"food_portion": "String",
"food_carb": "Float",
"food_protein": "Float",
"food_fat": "Float"
}
],
"water":
[
{
"day_id": "Integer",
"id": "Integer",
"water_ml": "Float",
"water_percent": "Float",
"water_time": "Long"
},
{
"day_id": "Integer",
"id": "Integer",
"water_ml": "Float",
"water_percent": "Float",
"water_time": "Long"
},
{
"day_id": "Integer",
"id": "Integer",
"water_ml": "Float",
"water_percent": "Float",
"water_time": "Long"
}
]
}
]
您有3个核心表(在数据库注释的实体列表中定义的带注释的类)、天、餐和水。
如果(请参阅下文)您希望在天和餐之间以及天和水之间建立多对多关系,那么您将为每个多对多关系创建一个关联/映射/引用(和其他术语)表。这样的表有两列,一列唯一关联/引用/映射到天,另一列唯一关联/引用/映射到餐,用于天-餐,或者在天-水关联/引用/映射到水的情况下。通常关联/引用/映射到id列。
所以在你的情况下(如果按照标题),你会有两个这样的表。
为了提取相关数据(与相关膳食和相关水域的天数),您有一个POJO,其中嵌入了日期和与膳食的关系,使用关联注释和连接注释定义关联/参考/映射表,同样也定义了与水域的关系。
但是,您的JSON描述了两个一对多关系,而不是两个多对多关系。也就是说,Meals引用了父天,同样,Waters引用了父天。
在这种情况下,您只需要3个核心表。用于提取具有相关Meals和相关Waters的Day。您可以对Day使用@Embedded
注释,对Meals和Waters使用@Relation
,而没有@Associate
和@Juntion
,因为没有关联/引用/映射表。
工作示例此工作示例使用
所以这3个核心表(实体)天,水和饭。
Day(请注意,一行是Day,因此通常是Day表而不是Day表):-
@Entity
public class Day {
@PrimaryKey
Long dayId = null;
String date;
Float weight;
/* etc */
Day(){} /* Room will use this constructor */
@Ignore /* Tell Room to ignore this constructor, but still usable outside of Room, so makes life easier */
Day(String date, Float weight) {
this.dayId = null; /* not needed but effectively what happens */
this.date = date;
this.weight = weight;
}
/* No getters and setters required as members aren't private/protected */
}
一餐
@Entity(
/* Optional but suggested */
foreignKeys = {
@ForeignKey(
entity = Day.class,
parentColumns = {"dayId"},
childColumns = {"dayId_Meal_Map"}
/* Optional but can be useful */
, onDelete = ForeignKey.CASCADE
, onUpdate = ForeignKey.CASCADE
)
}
)
class Meal {
@PrimaryKey
Long mealId=null;
@ColumnInfo(index = true)
long dayId_Meal_Map;
String food_meal_time;
/* etc */
Meal(){}
@Ignore
Meal(long parentDayId, String food_meal_time) {
this.dayId_Meal_Map = parentDayId;
this.food_meal_time = food_meal_time;
}
@Ignore
Meal(String food_meal_time) {
this.food_meal_time = food_meal_time;
}
}
水
@Entity(
/* Optional but suggested */
foreignKeys = {
@ForeignKey(
entity = Day.class,
parentColumns = {"dayId"},
childColumns = {"dayId_Water_Map"}
/* Optional but can be useful */
, onDelete = ForeignKey.CASCADE
, onUpdate = ForeignKey.CASCADE
)
}
)
class Water {
@PrimaryKey
Long waterId=null;
@ColumnInfo(index = true)
long dayId_Water_Map;
Float water_ml;
/* etc */
Water(){}
@Ignore
Water(long parentDayId, Float water_ml) {
this.dayId_Water_Map = parentDayId;
this.water_ml = water_ml;
}
/* Constructor for m2m i.e. reference to dayId is not needed as in the mapping table */
@Ignore
Water(Float water_ml) {
this.water_ml = water_ml;
}
}
对于多-多关系,然后2个映射表DayMealMap和DayWaterMap
DayMealMap公司
@Entity(
primaryKeys = {"dayMealMap_dayId_Reference","dayMealMap_mealId_Reference"},
/* Optional but suggested */
foreignKeys = {
@ForeignKey(
entity = Day.class,
parentColumns = {"dayId"},
childColumns = {"dayMealMap_dayId_Reference"}
/* Optional but helpful */
, onDelete = ForeignKey.CASCADE
, onUpdate = ForeignKey.CASCADE
),
@ForeignKey(
entity = Meal.class,
parentColumns = "mealId",
childColumns = "dayMealMap_mealId_Reference"
, onDelete = ForeignKey.CASCADE
, onUpdate = ForeignKey.CASCADE
)
}
)
class DayMealMap {
long dayMealMap_dayId_Reference;
/* Index optional but would likely improve efficiency */
/* Also ROOM will issue warning if not indexed */
@ColumnInfo(index = true)
long dayMealMap_mealId_Reference;
DayMealMap(){}
@Ignore
DayMealMap(long dayIdMap, long mealIdMap) {
this.dayMealMap_dayId_Reference = dayIdMap;
this.dayMealMap_mealId_Reference = mealIdMap;
}
}
水务地图
@Entity(
primaryKeys = {"dayWaterMap_dayId_Reference","dayWaterMap_waterId_Reference"},
foreignKeys = {
@ForeignKey(
entity = Day.class,
parentColumns = "dayId",
childColumns = "dayWaterMap_dayId_Reference"
, onDelete = ForeignKey.CASCADE
, onUpdate = ForeignKey.CASCADE
),
@ForeignKey(
entity = Water.class,
parentColumns = "waterId",
childColumns = "dayWaterMap_waterId_Reference"
,onDelete = ForeignKey.CASCADE
,onUpdate = ForeignKey.CASCADE
)
}
)
class DayWaterMap {
long dayWaterMap_dayId_Reference;
@ColumnInfo(index = true)
long dayWaterMap_waterId_Reference;
DayWaterMap(){}
@Ignore
DayWaterMap(long dayIdMap, long waterIdMap) {
this.dayWaterMap_dayId_Reference = dayIdMap;
this.dayWaterMap_waterId_Reference = waterIdMap;
}
}
通过1-M关系提取相关膳食和水的天数,然后使用POJO
class DayWithRelatedMealsAlsoWithRelatedWaters {
@Embedded
Day day;
@Relation(
entity = Meal.class,
parentColumn = "dayId",
entityColumn = "dayId_Meal_Map"
)
List<Meal> mealList;
@Relation(
entity = Water.class,
parentColumn = "dayId",
entityColumn = "dayId_Water_Map"
)
List<Water> waterList;
}
对于Many-Many,为了获得相同的相关数据,它是POJO(通过映射表(也称为关联表))
class M2MDayWithRelatedMealsAlsoWithRealtedWaters {
@Embedded
Day day;
@Relation(
entity = Meal.class,
parentColumn = "dayId",
entityColumn = "mealId",
associateBy = @Junction(
value = DayMealMap.class,
parentColumn = "dayMealMap_dayId_Reference",
entityColumn = "dayMealMap_mealId_Reference"
)
)
List<Meal> mealList;
@Relation(
entity = Water.class,
parentColumn = "dayId",
entityColumn = "waterId",
associateBy = @Junction(
value = DayWaterMap.class,
parentColumn = "dayWaterMap_dayId_Reference",
entityColumn = "dayWaterMap_waterId_Reference"
)
)
List<Water> waterList;
}
一个带注释的抽象类(可以是一个接口,但我更喜欢抽象类,因为它更灵活(原因超越了这个问题))
AllDao(即为了方便起见,将所有DAO方法放在一起):-
@Dao
abstract class AllDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(Day day);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(Meal meal);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(Water water);
/* For many-many mapping table inserts */
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(DayMealMap dayMealMap);
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract long insert(DayWaterMap dayWaterMap);
@Transaction
@Query("SELECT * FROM day")
abstract List<DayWithRelatedMealsAlsoWithRelatedWaters> getListOfDaysWithRelatedMealsAndRelatedWaters();
@Transaction
@Query("SELECT * FROM day")
abstract List<M2MDayWithRelatedMealsAlsoWithRealtedWaters> getM2mListOfDaysWithRelatedMealsAlsoWithRelatedWaters();
}
从Room的角度开始将所有这些放在一起,即@Database
注释类。
@Database(
entities = {
/* Either 1-many or many-many use the 3 core tables */
Day.class,
Meal.class,
Water.class
/* for many-many then the 2 mapping tables */
, DayMealMap.class
, DayWaterMap.class
},
version = 1,
exportSchema = false
)
abstract class TheDatabase extends RoomDatabase {
abstract AllDao getAllDao();
private volatile static TheDatabase INSTANCE= null;
public static TheDatabase getINSTANCE(Context context) {
if (INSTANCE==null) {
INSTANCE = Room.databaseBuilder(context,TheDatabase.class,"the_database.db")
.allowMainThreadQueries()
.build();
}
return INSTANCE;
}
}
。allowMainThreadQueries用于方便和简洁/清晰
实际上使用上述所有内容来添加一些数据,然后提取两种类型的房地产的数据:-
主要活动
public class MainActivity extends AppCompatActivity {
TheDatabase mDB;
AllDao mDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDB = TheDatabase.getINSTANCE(this);
mDao = mDB.getAllDao();
/* 1-many */
long day001Id = mDao.insert(new Day("2022-07-08",10.10F));
long day002Id = mDao.insert(new Day("2022-07-09",11.11F));
long day003Id = mDao.insert(new Day("2022-07-09",12.12F));
/* Add some related Meals (1-M) */
long m011Id = mDao.insert(new Meal(day001Id,"09:00"));
long m012Id = mDao.insert(new Meal(day001Id,"11:00"));
long m013Id = mDao.insert(new Meal(day001Id,"13:00"));
long m014Id = mDao.insert(new Meal(day001Id,"18:00"));
long m015Id = mDao.insert(new Meal(day001Id,"21:00"));
long m021Id = mDao.insert(new Meal(day002Id,"09:30"));
long m022Id = mDao.insert(new Meal(day002Id,"10:15"));
long m023Id = mDao.insert(new Meal(day002Id,"12:45"));
long m024Id = mDao.insert(new Meal(day002Id,"17:30"));
long m025Id = mDao.insert(new Meal(day002Id,"20:30"));
/* Add some Waters (1-M) */
long w011Id = mDao.insert(new Water(day001Id,100.100F));
long w012Id = mDao.insert(new Water(day001Id,200.200F));
long w021Id = mDao.insert(new Water(day002Id, 120.12F));
long w022Id = mDao.insert(new Water(day002Id, 220.22F));
/* Use the above Days, Meals and Waters to add M2M stuff */
/* Day 1 just a subset of the 1-m's */
mDao.insert(new DayMealMap(day001Id,m011Id));
mDao.insert(new DayMealMap(day001Id,m013Id));
mDao.insert(new DayMealMap(day001Id,m015Id));
/* Day 2 just a subset of 1-m's */
mDao.insert(new DayMealMap(day002Id, m022Id));
mDao.insert(new DayMealMap(day002Id,m024Id));
/* Note with 1-M day 3 was empty, this relates existing meals from day 1 and day 2 to day 3 */
mDao.insert(new DayMealMap(day003Id,m011Id));
mDao.insert(new DayMealMap(day003Id,m021Id));
for (DayWithRelatedMealsAlsoWithRelatedWaters d: mDao.getListOfDaysWithRelatedMealsAndRelatedWaters()) {
logADayWithRelatedMealsAndWaters(d,"_1-M");
}
for (M2MDayWithRelatedMealsAlsoWithRealtedWaters m: mDao.getM2mListOfDaysWithRelatedMealsAlsoWithRelatedWaters()) {
logM2MDayWithRelatedMealsAndWaters(m,"_M-M");
}
}
private void logADayWithRelatedMealsAndWaters(DayWithRelatedMealsAlsoWithRelatedWaters dwrmawrw, String suffix) {
Log.d(
"DAYINFO" + suffix,
"Day is " + dwrmawrw.day.date +
" Weight is " + dwrmawrw.day.weight +
" ID is " + dwrmawrw.day.dayId
+ " The Day has " + dwrmawrw.mealList.size() + " meal(s) "
+ " and it has " + dwrmawrw.waterList.size() + " water(s)."
);
for (Meal m: dwrmawrw.mealList) {
Log.d(
"DAYINFO" + suffix,
"\tMeal is " + m.food_meal_time + " it's parent Day has the ID " + m.dayId_Meal_Map
);
}
for (Water w: dwrmawrw.waterList) {
Log.d(
"DAYINFO" + suffix,
"\tWater is " + w.water_ml + " it's parent Day has the ID " + w.dayId_Water_Map
);
}
}
private void logM2MDayWithRelatedMealsAndWaters(M2MDayWithRelatedMealsAlsoWithRealtedWaters mdwrmawrw, String suffix) {
Log.d(
"DAYINFO" + suffix,
"Day is " + mdwrmawrw.day.date +
" Weight is " + mdwrmawrw.day.weight +
" ID is " + mdwrmawrw.day.dayId
+ " The Day has " + mdwrmawrw.mealList.size() + " meal(s) "
+ " and it has " + mdwrmawrw.waterList.size() + " water(s)."
);
for (Meal m: mdwrmawrw.mealList) {
Log.d(
"DAYINFO" + suffix,
"\tMeal is " + m.food_meal_time + " it's parent Day has the ID " + m.dayId_Meal_Map
);
}
for (Water w: mdwrmawrw.waterList) {
Log.d(
"DAYINFO" + suffix,
"\tWater is " + w.water_ml + " it's parent Day has the ID " + w.dayId_Water_Map
);
}
}
}
注:以上仅设计为运行一次作为演示
结果(即写入日志的输出,添加空格以分割两种类型的关系):-
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Day is 2022-07-08 Weight is 10.1 ID is 1 The Day has 5 meal(s) and it has 2 water(s).
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Meal is 09:00 it's parent Day has the ID 1
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Meal is 11:00 it's parent Day has the ID 1
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Meal is 13:00 it's parent Day has the ID 1
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Meal is 18:00 it's parent Day has the ID 1
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Meal is 21:00 it's parent Day has the ID 1
2022-07-08 12:20:01.522 D/DAYINFO_1-M: Water is 100.1 it's parent Day has the ID 1
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Water is 200.2 it's parent Day has the ID 1
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Day is 2022-07-09 Weight is 11.11 ID is 2 The Day has 5 meal(s) and it has 2 water(s).
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Meal is 09:30 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Meal is 10:15 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Meal is 12:45 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Meal is 17:30 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Meal is 20:30 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Water is 120.12 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Water is 220.22 it's parent Day has the ID 2
2022-07-08 12:20:01.523 D/DAYINFO_1-M: Day is 2022-07-09 Weight is 12.12 ID is 3 The Day has 0 meal(s) and it has 0 water(s).
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Day is 2022-07-08 Weight is 10.1 ID is 1 The Day has 3 meal(s) and it has 0 water(s).
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Meal is 09:00 it's parent Day has the ID 1
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Meal is 13:00 it's parent Day has the ID 1
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Meal is 21:00 it's parent Day has the ID 1
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Day is 2022-07-09 Weight is 11.11 ID is 2 The Day has 2 meal(s) and it has 0 water(s).
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Meal is 10:15 it's parent Day has the ID 2
2022-07-08 12:20:01.527 D/DAYINFO_M-M: Meal is 17:30 it's parent Day has the ID 2
2022-07-08 12:20:01.528 D/DAYINFO_M-M: Day is 2022-07-09 Weight is 12.12 ID is 3 The Day has 2 meal(s) and it has 0 water(s).
2022-07-08 12:20:01.528 D/DAYINFO_M-M: Meal is 09:00 it's parent Day has the ID 1
2022-07-08 12:20:01.528 D/DAYINFO_M-M: Meal is 09:30 it's parent Day has the ID 2
可以看出,相关数据取决于关系类型,并且有目的地应用数据来突出差异。
问题内容: 在关系数据库中,我有一个用户表,一个类别表和一个用户类别表,它们之间存在多对多关系。在Redis中具有这种结构的更好形式是什么? 问题答案: 使用Redis,关系通常由集合表示。一组可用于表示单向关系,因此每个对象需要一组以表示多对多关系。 尝试将关系数据库模型与Redis数据结构进行比较是毫无用处的。使用Redis,所有内容均以非规范化方式存储。 例: 一旦有了此数据结构,就可以使用
问题内容: 我有以下实体关系问题。一个“游戏”必须有两个(只有两个)“团队”对象。一个“团队”可以有很多“游戏” 据我所知,这是一对多关系。但是…我不知道如何在JPA中对此建模。例如,我打算做这样的事情… 但是,正如您所看到的,我不确定如何从注释侧将表链接在一起。有人曾经做过这样的事情吗?有什么想法吗? 非常感谢! 问题答案: 我希望有人能提出一个很棒的解决方案,但是这是一个棘手的情况,我从未能找
问题内容: 我有2张桌子: 电影:movieID 用户:userID 这些表通过Queue表具有多对多关系,并带有一个附加属性listOrder: 队列:movieID,userID,listOrder 我正在尝试使用EclipseLink对此模型建模,但是却收到“不兼容映射”错误。这是我的代码的示例: QueueItemPK的目的是使我可以拥有movieID和userID的复合主键。我不确定这是
首先,我的英语很差,如果我的写作让人困惑,请原谅。 我试图在实例之间创建以下关系:如果,和,那么。在我的例子中,我想指定如果一个“管理”一名员工,并且与有相同的工作,那么他也管理同一名员工。 我尝试使用链属性来实现这一点,但当我激活它时,推理器(事实1.6.5)不起作用(日志显示使用了一个非简单属性)。我认为问题在于属性“manages”是不对称的和不可伸缩的,而属性“sameJob”是可传递的和
基础回购 和存储库类 现在我想使用带有谓词查询的Repo。我需要形成一个谓词,在这个谓词中,我可以根据给定的Bs加载
我需要创建一个学生管理系统,它可以帮助多个老师教多个学生,多个学生可以有多个老师。现在我已经在下面创建了一个代码。另外,如果你认为有更好的方法来实现我的目标,请指导,我对多对多的关系是新的,互联网上有这么多方法,这只是让人困惑: 错误是: