如何在 Android 中存储带有嵌套对象数据的数据? [房间]
How can I store data with nested object data in Android? [Room]
我有一个高维数据集,它提供了一个 json 结构(大约 3000 个对象,每个对象的数组和该数组中的几十个对象。)我在截击的帮助下阅读了它们图书馆。我想保存这些数据。在数据库中并轻松访问它。我该怎么做
我找不到房间的例子
JSON数据
{
"MyData": [
{
"food_id": "1",
"food_name": "Food 1",
"food_image": "imageurl",
"food_kcal": "32",
"food_url": "url",
"food_description": "desc",
"carb_percent": "72",
"protein_percent": "23",
"fat_percent": "4",
"units": [
{
"unit": "Unit A",
"amount": "735.00",
"calory": "75.757",
"calcium": "8.580",
"carbohydrt": "63.363",
"cholestrl": "63.0",
"fiber_td": "56.12",
"iron": "13.0474",
"lipid_tot": "13.01",
"potassium": "11.852",
"protein": "717.1925",
"sodium": "112.02",
"vit_a_iu": "110.7692",
"vit_c": "110.744"
},
{
"unit": "Unit C",
"amount": "32.00",
"calory": "23.757",
"calcium": "53.580",
"carbohydrt": "39.363",
"cholestrl": "39.0",
"fiber_td": "93.12",
"iron": "93.0474",
"lipid_tot": "93.01",
"potassium": "9.852",
"protein": "72.1925",
"sodium": "10.0882",
"vit_a_iu": "80.7692",
"vit_c": "80.744"
}
]
},
{
"food_id": "2",
"food_name": "Food 2",
"food_image": "imageurl",
"food_kcal": "50",
"food_url": "url",
"food_description": "desc",
"carb_percent": "25",
"protein_percent": "14",
"fat_percent": "8",
"units": [
{
"unit": "Unit A",
"amount": "25.00",
"calory": "25.757",
"calcium": "55.580",
"carbohydrt": "53.363",
"cholestrl": "53.0",
"fiber_td": "53.12",
"iron": "53.0474",
"lipid_tot": "53.01",
"potassium": "17.852",
"protein": "757.1925",
"sodium": "122.02",
"vit_a_iu": "10.7692",
"vit_c": "10.744"
},
{
"unit": "Unit C",
"amount": "2.00",
"calory": "2.757",
"calcium": "5.580",
"carbohydrt": "3.363",
"cholestrl": "3.0",
"fiber_td": "3.12",
"iron": "3.0474",
"lipid_tot": "3.01",
"potassium": "77.852",
"protein": "77.1925",
"sodium": "12.02",
"vit_a_iu": "0.7692",
"vit_c": "0.744"
},
{
"unit": "Unit G",
"amount": "1.00",
"calory": "2.1",
"calcium": "0.580",
"carbohydrt": "0.363",
"cholestrl": "0.0",
"fiber_td": "0.12",
"iron": "0.0474",
"lipid_tot": "0.01",
"potassium": "5.852",
"protein": "0.1925",
"sodium": "1.02",
"vit_a_iu": "0.7692",
"vit_c": "0.744"
}
]
}
]
}
对于SQLite
您要做的第一件事是确定数据库的模式。
查看您的数据,您有很多 MyData 对象,每个对象都有 0 个或多个 Unit 对象。
因此您可以对 MyData 对象使用 table,对 Unit 对象使用 table。每个 Unit 都有一个父 MyData 对象。因此,除了每个单元的数据之外,您还可以有一个引用(映射、关联)MyData 的列(可能是 food_id 假设它唯一标识 MyData)。
使用缩短版的 MyData(仅 food_id、food_name)和缩短版的单位(单位、数量和卡路里)来演示您可以有两个 class是:-
class MyData {
public static final String TABLE_NAME = "_mydata";
public static final String COLUMN_FOOD_ID = "_food_id";
public static final String COLUMN_FOOD_NAME = "_food_name";
long food_id;
String food_name;
Unit[] units;
public MyData(long food_id, String food_name, Unit[] units) {
this.food_id = food_id;
this.food_name = food_name;
this.units = units;
}
}
和
class Unit {
public static final String TABLE_NAME = "_unit";
public static final String COLUMN_UNIT = "_unit";
public static final String COLUMN_AMOUNT = "_amount";
public static final String COLUMN_CALORY = "_calory";
public static final String COLUMN_FOOD_ID_PARENT ="parent_food_id";
String unit;
double amount;
double calory;
public Unit(String unit, double amount, double calory) {
this.unit = unit;
this.amount = amount;
this.calory = calory;
}
}
注意将用于 table 的常量,即模式。为简洁起见,将它们放在 classes 中,它们可以在其他地方编码。
注意附加列 parent_food_id,这将用于引用父 food_id.
所以架构将(可能)看起来像
- Table _mydata 有 2 列(易于添加更多)
- food_id(这将是唯一的(PRIMARY KEY)并且因为该值是整数,如果 SQLite 则为 INTEGER 类型),以及
- food_name(因为它是一个字符串,然后在 SQLite 中输入 TEXT)。
- Table _unit 有 4 列
- _unit(因为它是一个字符串然后在 SQLite 中输入 TEXT)
- _amount(因为它是浮点类型,所以在 SQLite 中是 REAL)
- _calory(因为它是一个浮点类型,所以在 SQLite 中是 REAL)
- parent_food_id 因为它指的是 food_id 是 INTEGER 那么它将是 INTEGER。
- 因为它是在 2 个 table 之间建立关系的原因,所以应该要求它确实引用了 food_id。尽管不是必需的,但最好为此强制执行引用的完整性(引用完整性),可以添加外键约束。
- 拥有一个主键总是明智的,但由于其他 MyData 对象的单位和/或数量和/或卡路里可能具有相同的值,所以这三者的组合不太可能相同.所以主键是所有 3 列。
在 SQLite 术语中,将创建上述内容的 SQL(每个 table 一个)可能是:-
CREATE TABLE _mydata(_food_id INTEGER PRIMARY KEY,_food_name TEXT)
,以及
CREATE TABLE _unit(_unit TEXT,_amount REAL,_calory REAL,parent_food_id INTEGER REFERENCES _mydata(_food_id) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY(_unit,_amount,_calory))
处理数据库
使用 Android 和 SQLite 那么典型的方法是利用扩展 SQLiteOpenHelper 的 DatabaseHelper。 SQLiteOpenHelpr 需要 2 个覆盖方法 onCreate 和 onUpgrae
- onCreate 运行s 数据库创建时。
- 它 运行 只为数据库的存在而持续存在一次,即它只会 运行 当应用程序是第一个时 运行.
- 此方法通常用于定义entities/components如tables.
- onUpgrade 运行s 传递给 SQLiteOpenHelper 的数据库版本大于从数据库本身提取的版本号。
通常是访问数据库的代码,例如添加、删除、更新、删除或提取数据。
为了演示,数据库将只有将数据插入 table 的方法。另外一种方法将采用 JSON 字符串(相当于一个文件)并填充 tables.
所以 DatabaseHelper class 可以是 :-
class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "my_database.db";
public static final int DATABASE_VERSION = 1;
private SQLiteDatabase db;
private static volatile DatabaseHelper instance = null;
private DatabaseHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
db = this.getWritableDatabase();
}
/* Use a singleton approach */
public static DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context);
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + MyData.TABLE_NAME + "(" +
MyData.COLUMN_FOOD_ID + " INTEGER PRIMARY KEY," +
MyData.COLUMN_FOOD_NAME + " TEXT" +
")"
);
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + Unit.TABLE_NAME + "(" +
Unit.COLUMN_UNIT + " TEXT," +
Unit.COLUMN_AMOUNT + " REAL," +
Unit.COLUMN_CALORY + " REAL," +
Unit.COLUMN_FOOD_ID_PARENT +
/* Foreign Key Constraint to enforce referential integrity*/
" INTEGER REFERENCES " + MyData.TABLE_NAME + "(" + MyData.COLUMN_FOOD_ID + ") " +
/* These make maintaining referential integrity easier */
"ON DELETE CASCADE " +
"ON UPDATE CASCADE, " +
/* define the primary key */
" PRIMARY KEY(" +
Unit.COLUMN_UNIT + "," + Unit.COLUMN_AMOUNT + "," + Unit.COLUMN_CALORY +
")" +
")"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
/* not expecting to increase the database version so leave this to do nothing */
}
public long insertMyData(MyData myData) {
ContentValues cv = new ContentValues();
cv.put(MyData.COLUMN_FOOD_ID,myData.food_id);
cv.put(MyData.COLUMN_FOOD_NAME,myData.food_name);
return db.insert(MyData.TABLE_NAME,null,cv);
}
public long insertUnit(Unit unit, long parentId) {
ContentValues cv = new ContentValues();
cv.put(Unit.COLUMN_UNIT,unit.unit);
cv.put(Unit.COLUMN_AMOUNT,unit.amount);
cv.put(Unit.COLUMN_CALORY,unit.calory);
cv.put(Unit.COLUMN_FOOD_ID_PARENT,parentId);
return db.insert(Unit.TABLE_NAME,null,cv);
}
public void massInsert(String jsonString) {
MyData[] extracted = new Gson().fromJson(jsonString,MyData[].class);
db.beginTransaction();
for(MyData m: new Gson().fromJson(jsonString,MyData[].class)) {
long food_id = insertMyData(m);
if (food_id > 0) {
for(Unit u: m.units) {
insertUnit(u,food_id);
}
}
}
db.setTransactionSuccessful();
db.endTransaction();
}
}
演示
下面是在activity中使用上面的演示,即MainActivity:-
public class MainActivity extends AppCompatActivity {
MyData[] TESTDATA = {
new MyData(
1,
"Bat",
new Unit[]{
new Unit("Unit A",15.0000,32.4877372383),
new Unit("Unit C",110.0000,238.243404414),
new Unit("Unit F",1.0000,2.16584914922)
}
),
new MyData(
2,
"Another",
new Unit[]{
new Unit("Unit A",17.0000,3.4877372383),
new Unit("Unit C",10.0000,382.243404414),
new Unit("Unit F",3.0000,5.16584914922)
}
),
};
DatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String test = new Gson().toJson(TESTDATA);
Log.d("APPINFO","TESTDATA as JSON is\n\t" + test);
//MyData[] extracted = new Gson().fromJson(test,MyData[].class);
dbHelper = DatabaseHelper.getInstance(this); // Prepare to use the database
dbHelper.massInsert(test); // Actually use the database to insert the data
/* Example of extracting data using a JOIN to combine the MyData and the related Units */
Cursor csr = dbHelper.getWritableDatabase().query(
MyData.TABLE_NAME + " JOIN " + Unit.TABLE_NAME + " ON " + Unit.COLUMN_FOOD_ID_PARENT + "=" + MyData.COLUMN_FOOD_ID,
null,null,null,null,null,null
);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
结果
当 运行 日志包括:-
2022-01-08 07:32:14.666 D/APPINFO: TESTDATA as JSON is
[{"food_id":1,"food_name":"Bat","units":[{"amount":15.0,"calory":32.4877372383,"unit":"Unit A"},{"amount":110.0,"calory":238.243404414,"unit":"Unit C"},{"amount":1.0,"calory":2.16584914922,"unit":"Unit F"}]},{"food_id":2,"food_name":"Another","units":[{"amount":17.0,"calory":3.4877372383,"unit":"Unit A"},{"amount":10.0,"calory":382.243404414,"unit":"Unit C"},{"amount":3.0,"calory":5.16584914922,"unit":"Unit F"}]}]
和
2022-01-08 07:32:14.698 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f302fce
2022-01-08 07:32:14.699 I/System.out: 0 {
2022-01-08 07:32:14.699 I/System.out: _food_id=1
2022-01-08 07:32:14.699 I/System.out: _food_name=Bat
2022-01-08 07:32:14.699 I/System.out: _unit=Unit A
2022-01-08 07:32:14.699 I/System.out: _amount=15
2022-01-08 07:32:14.699 I/System.out: _calory=32.4877
2022-01-08 07:32:14.699 I/System.out: parent_food_id=1
2022-01-08 07:32:14.699 I/System.out: }
2022-01-08 07:32:14.699 I/System.out: 1 {
2022-01-08 07:32:14.699 I/System.out: _food_id=1
2022-01-08 07:32:14.699 I/System.out: _food_name=Bat
2022-01-08 07:32:14.700 I/System.out: _unit=Unit C
2022-01-08 07:32:14.701 I/System.out: _amount=110
2022-01-08 07:32:14.701 I/System.out: _calory=238.243
2022-01-08 07:32:14.701 I/System.out: parent_food_id=1
2022-01-08 07:32:14.701 I/System.out: }
2022-01-08 07:32:14.701 I/System.out: 2 {
2022-01-08 07:32:14.701 I/System.out: _food_id=1
2022-01-08 07:32:14.701 I/System.out: _food_name=Bat
2022-01-08 07:32:14.701 I/System.out: _unit=Unit F
2022-01-08 07:32:14.701 I/System.out: _amount=1
2022-01-08 07:32:14.701 I/System.out: _calory=2.16585
2022-01-08 07:32:14.701 I/System.out: parent_food_id=1
2022-01-08 07:32:14.701 I/System.out: }
2022-01-08 07:32:14.702 I/System.out: 3 {
2022-01-08 07:32:14.702 I/System.out: _food_id=2
2022-01-08 07:32:14.702 I/System.out: _food_name=Another
2022-01-08 07:32:14.702 I/System.out: _unit=Unit A
2022-01-08 07:32:14.702 I/System.out: _amount=17
2022-01-08 07:32:14.702 I/System.out: _calory=3.48774
2022-01-08 07:32:14.702 I/System.out: parent_food_id=2
2022-01-08 07:32:14.702 I/System.out: }
2022-01-08 07:32:14.702 I/System.out: 4 {
2022-01-08 07:32:14.702 I/System.out: _food_id=2
2022-01-08 07:32:14.703 I/System.out: _food_name=Another
2022-01-08 07:32:14.703 I/System.out: _unit=Unit C
2022-01-08 07:32:14.703 I/System.out: _amount=10
2022-01-08 07:32:14.703 I/System.out: _calory=382.243
2022-01-08 07:32:14.703 I/System.out: parent_food_id=2
2022-01-08 07:32:14.703 I/System.out: }
2022-01-08 07:32:14.703 I/System.out: 5 {
2022-01-08 07:32:14.703 I/System.out: _food_id=2
2022-01-08 07:32:14.703 I/System.out: _food_name=Another
2022-01-08 07:32:14.703 I/System.out: _unit=Unit F
2022-01-08 07:32:14.703 I/System.out: _amount=3
2022-01-08 07:32:14.704 I/System.out: _calory=5.16585
2022-01-08 07:32:14.704 I/System.out: parent_food_id=2
2022-01-08 07:32:14.704 I/System.out: }
2022-01-08 07:32:14.704 I/System.out: <<<<<
使用 Android Studio 的 App Inspection 数据库看起来像 :-
和
我有一个高维数据集,它提供了一个 json 结构(大约 3000 个对象,每个对象的数组和该数组中的几十个对象。)我在截击的帮助下阅读了它们图书馆。我想保存这些数据。在数据库中并轻松访问它。我该怎么做
我找不到房间的例子
JSON数据
{
"MyData": [
{
"food_id": "1",
"food_name": "Food 1",
"food_image": "imageurl",
"food_kcal": "32",
"food_url": "url",
"food_description": "desc",
"carb_percent": "72",
"protein_percent": "23",
"fat_percent": "4",
"units": [
{
"unit": "Unit A",
"amount": "735.00",
"calory": "75.757",
"calcium": "8.580",
"carbohydrt": "63.363",
"cholestrl": "63.0",
"fiber_td": "56.12",
"iron": "13.0474",
"lipid_tot": "13.01",
"potassium": "11.852",
"protein": "717.1925",
"sodium": "112.02",
"vit_a_iu": "110.7692",
"vit_c": "110.744"
},
{
"unit": "Unit C",
"amount": "32.00",
"calory": "23.757",
"calcium": "53.580",
"carbohydrt": "39.363",
"cholestrl": "39.0",
"fiber_td": "93.12",
"iron": "93.0474",
"lipid_tot": "93.01",
"potassium": "9.852",
"protein": "72.1925",
"sodium": "10.0882",
"vit_a_iu": "80.7692",
"vit_c": "80.744"
}
]
},
{
"food_id": "2",
"food_name": "Food 2",
"food_image": "imageurl",
"food_kcal": "50",
"food_url": "url",
"food_description": "desc",
"carb_percent": "25",
"protein_percent": "14",
"fat_percent": "8",
"units": [
{
"unit": "Unit A",
"amount": "25.00",
"calory": "25.757",
"calcium": "55.580",
"carbohydrt": "53.363",
"cholestrl": "53.0",
"fiber_td": "53.12",
"iron": "53.0474",
"lipid_tot": "53.01",
"potassium": "17.852",
"protein": "757.1925",
"sodium": "122.02",
"vit_a_iu": "10.7692",
"vit_c": "10.744"
},
{
"unit": "Unit C",
"amount": "2.00",
"calory": "2.757",
"calcium": "5.580",
"carbohydrt": "3.363",
"cholestrl": "3.0",
"fiber_td": "3.12",
"iron": "3.0474",
"lipid_tot": "3.01",
"potassium": "77.852",
"protein": "77.1925",
"sodium": "12.02",
"vit_a_iu": "0.7692",
"vit_c": "0.744"
},
{
"unit": "Unit G",
"amount": "1.00",
"calory": "2.1",
"calcium": "0.580",
"carbohydrt": "0.363",
"cholestrl": "0.0",
"fiber_td": "0.12",
"iron": "0.0474",
"lipid_tot": "0.01",
"potassium": "5.852",
"protein": "0.1925",
"sodium": "1.02",
"vit_a_iu": "0.7692",
"vit_c": "0.744"
}
]
}
]
}
对于SQLite
您要做的第一件事是确定数据库的模式。
查看您的数据,您有很多 MyData 对象,每个对象都有 0 个或多个 Unit 对象。
因此您可以对 MyData 对象使用 table,对 Unit 对象使用 table。每个 Unit 都有一个父 MyData 对象。因此,除了每个单元的数据之外,您还可以有一个引用(映射、关联)MyData 的列(可能是 food_id 假设它唯一标识 MyData)。
使用缩短版的 MyData(仅 food_id、food_name)和缩短版的单位(单位、数量和卡路里)来演示您可以有两个 class是:-
class MyData {
public static final String TABLE_NAME = "_mydata";
public static final String COLUMN_FOOD_ID = "_food_id";
public static final String COLUMN_FOOD_NAME = "_food_name";
long food_id;
String food_name;
Unit[] units;
public MyData(long food_id, String food_name, Unit[] units) {
this.food_id = food_id;
this.food_name = food_name;
this.units = units;
}
}
和
class Unit {
public static final String TABLE_NAME = "_unit";
public static final String COLUMN_UNIT = "_unit";
public static final String COLUMN_AMOUNT = "_amount";
public static final String COLUMN_CALORY = "_calory";
public static final String COLUMN_FOOD_ID_PARENT ="parent_food_id";
String unit;
double amount;
double calory;
public Unit(String unit, double amount, double calory) {
this.unit = unit;
this.amount = amount;
this.calory = calory;
}
}
注意将用于 table 的常量,即模式。为简洁起见,将它们放在 classes 中,它们可以在其他地方编码。
注意附加列 parent_food_id,这将用于引用父 food_id.
所以架构将(可能)看起来像
- Table _mydata 有 2 列(易于添加更多)
- food_id(这将是唯一的(PRIMARY KEY)并且因为该值是整数,如果 SQLite 则为 INTEGER 类型),以及
- food_name(因为它是一个字符串,然后在 SQLite 中输入 TEXT)。
- Table _unit 有 4 列
- _unit(因为它是一个字符串然后在 SQLite 中输入 TEXT)
- _amount(因为它是浮点类型,所以在 SQLite 中是 REAL)
- _calory(因为它是一个浮点类型,所以在 SQLite 中是 REAL)
- parent_food_id 因为它指的是 food_id 是 INTEGER 那么它将是 INTEGER。
- 因为它是在 2 个 table 之间建立关系的原因,所以应该要求它确实引用了 food_id。尽管不是必需的,但最好为此强制执行引用的完整性(引用完整性),可以添加外键约束。
- 拥有一个主键总是明智的,但由于其他 MyData 对象的单位和/或数量和/或卡路里可能具有相同的值,所以这三者的组合不太可能相同.所以主键是所有 3 列。
在 SQLite 术语中,将创建上述内容的 SQL(每个 table 一个)可能是:-
CREATE TABLE _mydata(_food_id INTEGER PRIMARY KEY,_food_name TEXT)
,以及CREATE TABLE _unit(_unit TEXT,_amount REAL,_calory REAL,parent_food_id INTEGER REFERENCES _mydata(_food_id) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY(_unit,_amount,_calory))
处理数据库
使用 Android 和 SQLite 那么典型的方法是利用扩展 SQLiteOpenHelper 的 DatabaseHelper。 SQLiteOpenHelpr 需要 2 个覆盖方法 onCreate 和 onUpgrae
- onCreate 运行s 数据库创建时。
- 它 运行 只为数据库的存在而持续存在一次,即它只会 运行 当应用程序是第一个时 运行.
- 此方法通常用于定义entities/components如tables.
- onUpgrade 运行s 传递给 SQLiteOpenHelper 的数据库版本大于从数据库本身提取的版本号。
通常是访问数据库的代码,例如添加、删除、更新、删除或提取数据。
为了演示,数据库将只有将数据插入 table 的方法。另外一种方法将采用 JSON 字符串(相当于一个文件)并填充 tables.
所以 DatabaseHelper class 可以是 :-
class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "my_database.db";
public static final int DATABASE_VERSION = 1;
private SQLiteDatabase db;
private static volatile DatabaseHelper instance = null;
private DatabaseHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
db = this.getWritableDatabase();
}
/* Use a singleton approach */
public static DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context);
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + MyData.TABLE_NAME + "(" +
MyData.COLUMN_FOOD_ID + " INTEGER PRIMARY KEY," +
MyData.COLUMN_FOOD_NAME + " TEXT" +
")"
);
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + Unit.TABLE_NAME + "(" +
Unit.COLUMN_UNIT + " TEXT," +
Unit.COLUMN_AMOUNT + " REAL," +
Unit.COLUMN_CALORY + " REAL," +
Unit.COLUMN_FOOD_ID_PARENT +
/* Foreign Key Constraint to enforce referential integrity*/
" INTEGER REFERENCES " + MyData.TABLE_NAME + "(" + MyData.COLUMN_FOOD_ID + ") " +
/* These make maintaining referential integrity easier */
"ON DELETE CASCADE " +
"ON UPDATE CASCADE, " +
/* define the primary key */
" PRIMARY KEY(" +
Unit.COLUMN_UNIT + "," + Unit.COLUMN_AMOUNT + "," + Unit.COLUMN_CALORY +
")" +
")"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
/* not expecting to increase the database version so leave this to do nothing */
}
public long insertMyData(MyData myData) {
ContentValues cv = new ContentValues();
cv.put(MyData.COLUMN_FOOD_ID,myData.food_id);
cv.put(MyData.COLUMN_FOOD_NAME,myData.food_name);
return db.insert(MyData.TABLE_NAME,null,cv);
}
public long insertUnit(Unit unit, long parentId) {
ContentValues cv = new ContentValues();
cv.put(Unit.COLUMN_UNIT,unit.unit);
cv.put(Unit.COLUMN_AMOUNT,unit.amount);
cv.put(Unit.COLUMN_CALORY,unit.calory);
cv.put(Unit.COLUMN_FOOD_ID_PARENT,parentId);
return db.insert(Unit.TABLE_NAME,null,cv);
}
public void massInsert(String jsonString) {
MyData[] extracted = new Gson().fromJson(jsonString,MyData[].class);
db.beginTransaction();
for(MyData m: new Gson().fromJson(jsonString,MyData[].class)) {
long food_id = insertMyData(m);
if (food_id > 0) {
for(Unit u: m.units) {
insertUnit(u,food_id);
}
}
}
db.setTransactionSuccessful();
db.endTransaction();
}
}
演示
下面是在activity中使用上面的演示,即MainActivity:-
public class MainActivity extends AppCompatActivity {
MyData[] TESTDATA = {
new MyData(
1,
"Bat",
new Unit[]{
new Unit("Unit A",15.0000,32.4877372383),
new Unit("Unit C",110.0000,238.243404414),
new Unit("Unit F",1.0000,2.16584914922)
}
),
new MyData(
2,
"Another",
new Unit[]{
new Unit("Unit A",17.0000,3.4877372383),
new Unit("Unit C",10.0000,382.243404414),
new Unit("Unit F",3.0000,5.16584914922)
}
),
};
DatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String test = new Gson().toJson(TESTDATA);
Log.d("APPINFO","TESTDATA as JSON is\n\t" + test);
//MyData[] extracted = new Gson().fromJson(test,MyData[].class);
dbHelper = DatabaseHelper.getInstance(this); // Prepare to use the database
dbHelper.massInsert(test); // Actually use the database to insert the data
/* Example of extracting data using a JOIN to combine the MyData and the related Units */
Cursor csr = dbHelper.getWritableDatabase().query(
MyData.TABLE_NAME + " JOIN " + Unit.TABLE_NAME + " ON " + Unit.COLUMN_FOOD_ID_PARENT + "=" + MyData.COLUMN_FOOD_ID,
null,null,null,null,null,null
);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
结果
当 运行 日志包括:-
2022-01-08 07:32:14.666 D/APPINFO: TESTDATA as JSON is
[{"food_id":1,"food_name":"Bat","units":[{"amount":15.0,"calory":32.4877372383,"unit":"Unit A"},{"amount":110.0,"calory":238.243404414,"unit":"Unit C"},{"amount":1.0,"calory":2.16584914922,"unit":"Unit F"}]},{"food_id":2,"food_name":"Another","units":[{"amount":17.0,"calory":3.4877372383,"unit":"Unit A"},{"amount":10.0,"calory":382.243404414,"unit":"Unit C"},{"amount":3.0,"calory":5.16584914922,"unit":"Unit F"}]}]
和
2022-01-08 07:32:14.698 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f302fce
2022-01-08 07:32:14.699 I/System.out: 0 {
2022-01-08 07:32:14.699 I/System.out: _food_id=1
2022-01-08 07:32:14.699 I/System.out: _food_name=Bat
2022-01-08 07:32:14.699 I/System.out: _unit=Unit A
2022-01-08 07:32:14.699 I/System.out: _amount=15
2022-01-08 07:32:14.699 I/System.out: _calory=32.4877
2022-01-08 07:32:14.699 I/System.out: parent_food_id=1
2022-01-08 07:32:14.699 I/System.out: }
2022-01-08 07:32:14.699 I/System.out: 1 {
2022-01-08 07:32:14.699 I/System.out: _food_id=1
2022-01-08 07:32:14.699 I/System.out: _food_name=Bat
2022-01-08 07:32:14.700 I/System.out: _unit=Unit C
2022-01-08 07:32:14.701 I/System.out: _amount=110
2022-01-08 07:32:14.701 I/System.out: _calory=238.243
2022-01-08 07:32:14.701 I/System.out: parent_food_id=1
2022-01-08 07:32:14.701 I/System.out: }
2022-01-08 07:32:14.701 I/System.out: 2 {
2022-01-08 07:32:14.701 I/System.out: _food_id=1
2022-01-08 07:32:14.701 I/System.out: _food_name=Bat
2022-01-08 07:32:14.701 I/System.out: _unit=Unit F
2022-01-08 07:32:14.701 I/System.out: _amount=1
2022-01-08 07:32:14.701 I/System.out: _calory=2.16585
2022-01-08 07:32:14.701 I/System.out: parent_food_id=1
2022-01-08 07:32:14.701 I/System.out: }
2022-01-08 07:32:14.702 I/System.out: 3 {
2022-01-08 07:32:14.702 I/System.out: _food_id=2
2022-01-08 07:32:14.702 I/System.out: _food_name=Another
2022-01-08 07:32:14.702 I/System.out: _unit=Unit A
2022-01-08 07:32:14.702 I/System.out: _amount=17
2022-01-08 07:32:14.702 I/System.out: _calory=3.48774
2022-01-08 07:32:14.702 I/System.out: parent_food_id=2
2022-01-08 07:32:14.702 I/System.out: }
2022-01-08 07:32:14.702 I/System.out: 4 {
2022-01-08 07:32:14.702 I/System.out: _food_id=2
2022-01-08 07:32:14.703 I/System.out: _food_name=Another
2022-01-08 07:32:14.703 I/System.out: _unit=Unit C
2022-01-08 07:32:14.703 I/System.out: _amount=10
2022-01-08 07:32:14.703 I/System.out: _calory=382.243
2022-01-08 07:32:14.703 I/System.out: parent_food_id=2
2022-01-08 07:32:14.703 I/System.out: }
2022-01-08 07:32:14.703 I/System.out: 5 {
2022-01-08 07:32:14.703 I/System.out: _food_id=2
2022-01-08 07:32:14.703 I/System.out: _food_name=Another
2022-01-08 07:32:14.703 I/System.out: _unit=Unit F
2022-01-08 07:32:14.703 I/System.out: _amount=3
2022-01-08 07:32:14.704 I/System.out: _calory=5.16585
2022-01-08 07:32:14.704 I/System.out: parent_food_id=2
2022-01-08 07:32:14.704 I/System.out: }
2022-01-08 07:32:14.704 I/System.out: <<<<<
使用 Android Studio 的 App Inspection 数据库看起来像 :-
和