我有3个POJO课程。 Recipe
,Ingredient
和Step
。
我希望能够在离线时浏览我的食谱,所以我决定使用Room
。
Recipe.class
@Entity(tableName = "recipe")
public class Recipe implements Parcelable {
@PrimaryKey(autoGenerate = false)
@SerializedName("id")
public int recipeId;
@ColumnInfo(name = "recipe_name")
public String name;
@TypeConverters(Converters.class)
public List<Ingredient> ingredients = null;
@TypeConverters(Converters.class)
public List<Step> steps = null;
@ColumnInfo(name = "recipe_servings")
public int servings;
@Ignore
public String image;
public Recipe(int recipeId, String name, List<Ingredient> ingredients, List<Step> steps, int servings, String image) {
this.recipeId = recipeId;
this.name = name;
this.ingredients = ingredients;
this.steps = steps;
this.servings = servings;
this.image = image;
}
...
//getters and setters
...
Converters.class
public class Converters {
static Gson gson = new Gson();
@TypeConverter
public static List<Ingredient> stringToIngredientList(String data) {
if (data == null) {
return Collections.emptyList();
}
Type listType = new TypeToken<List<Ingredient>>() {}.getType();
return gson.fromJson(data, listType);
}
@TypeConverter
public static String ingredientListToString(List<Ingredient> ingredients) {
return gson.toJson(ingredients);
}
@TypeConverter
public static List<Step> stringToStepList(String data) {
if (data == null) {
return Collections.emptyList();
}
Type listType = new TypeToken<List<Step>>() {}.getType();
return gson.fromJson(data, listType);
}
@TypeConverter
public static String stepListToString(List<Step> steps) {
return gson.toJson(steps);
}
}
RecipeDatabase.class
@Database(entities = {Recipe.class}, version = 1)
abstract class RecipeDatabase extends RoomDatabase {
private static RecipeDatabase INSTANCE;
public abstract RecipeDao recipeDao();
public static RecipeDatabase getRecipeDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(), RecipeDatabase.class, "recipe-database")
// allow queries on the main thread.
// Don't do this on a real app! See PersistenceBasicSample for an example.
.allowMainThreadQueries()
.build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
RecipeDao.class
@Dao
public interface RecipeDao {
@Query("SELECT * FROM recipe")
List<Recipe> getAll();
@Query("SELECT * FROM recipe where recipe_name LIKE :name")
Recipe findByName(String name);
@Query("SELECT COUNT(*) from recipe")
int countRecipes();
@Update
void update(Recipe... recipes);
@Insert
void insertAll(Recipe... recipes);
@Delete
void delete(Recipe recipe);
}
我的问题:使用List<Step>
课程将List<Ingredient>
和Strings
保存为Converters
后,我是否还应保存每个步骤的数据库。 class 和 Ingredient.class ?我是否应该为这些类添加@Entity
注释?我应该制作StepDatabase
和IngredientDatabase
吗?这还需要能够在离线时访问我的Recipes
吗?
答案 0 :(得分:1)
我还应该保存每个Step.class和Ingredient.class的数据库。我应该制作一个StepDatabase和一个IngredientDatabase吗?
总的来说不。您不按实体创建数据库,而是按实体创建表。在大多数应用中,一个数据库就足够了。
传统上,SQL数据库(本质上是关系数据库)应强制执行normalization rules,尤其是在服务器上的企业系统中。简而言之,规范化规则是指以父实体中的外键将每个实体提取到其自己的表中的方式,对关系数据库设计进行一系列重构。然后,您必须将SQL SELECT与JOIN一起使用才能将数据收集在一起。
话虽如此,打破移动应用程序的规范化规则并通过存储嵌套的实体(在您的情况下为成分)并将它们存储为JSON字符串或任何有意义的方式来保持数据模型尽可能简单是很常见的。方便您处理代码。
因此,总而言之,您目前所看到的情况确实不错。只要它可以简化您的代码-那就去吧。据我所知,Room不支持JOIN,但是有something pretty close。
有一个不错的article on Medium,它与Room讨论了高级主题。
答案 1 :(得分:0)
是的,在我看来,首先为每个表声明一个模型是一个好习惯,是的,每个模型都应该包含@Entity注释,告诉hibernate你所映射的是你db中的一个表。