在Android Studio中使用Room数据库关联表

时间:2019-05-27 13:00:48

标签: android database android-sqlite

如何关联两个表,以便创建与所附加图像相匹配的数据库。

Table

我了解到实验ID,日期,名称必须是父表的一部分,而试验编号,变量和结果是与父表相关联的子表。但是,我不太确定如何使用Entity和Dao在Room Database持久性中实现这一点。有人可以告诉我怎么做吗?

我希望结果是,如果用户在recyclerview中选择实验,则将导致另一个活动,在上方显示变量和结果的输入,以在顶部添加试验,同时在下方使用Recyclerview。

1 个答案:

答案 0 :(得分:0)

我相信以下工作示例是实现所需目标的方法之一。

代码

实验实体(表) Experiment.java

@Entity
public class Experiment {

    @PrimaryKey(autoGenerate = true)
    private long experimentId;
    private String experimentName;
    private String experimentDate;

    public Experiment() {
    }

    @Ignore
    public Experiment(String name, String date) {
        this.experimentName = name;
        this.experimentDate = date;
    }

    public long getExperimentId() {
        return experimentId;
    }

    public void setExperimentId(long experimentId) {
        this.experimentId = experimentId;
    }

    public String getExperimentName() {
        return experimentName;
    }

    public void setExperimentName(String experimentName) {
        this.experimentName = experimentName;
    }

    public String getExperimentDate() {
        return experimentDate;
    }

    public void setExperimentDate(String experimentDate) {
        this.experimentDate = experimentDate;
    }
}
  • 除了 @Ignore 的构造函数(为方便起见)以外,没有什么特别的

审判实体 Trial.java

@Entity
public class Trial {

    @PrimaryKey(autoGenerate = true)
    private long trialId;
    @ForeignKey(entity = Experiment.class, parentColumns = {BaseColumns._ID},childColumns = "parentExperiment", onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE)
    private long parentExperiment;
    private String trialVariable;
    private String trialResult;

    public Trial() {
    }

    @Ignore
    public Trial(long parentExperimentId, String variable, String result) {
        this.parentExperiment = parentExperimentId;
        this.trialVariable = variable;
        this.trialResult = result;
    }

    public long getTrialId() {
        return trialId;
    }

    public void setTrialId(long trialId) {
        this.trialId = trialId;
    }

    public long getParentExperiment() {
        return parentExperiment;
    }

    public void setParentExperiment(long parentExperiment) {
        this.parentExperiment = parentExperiment;
    }

    public String getTrialVariable() {
        return trialVariable;
    }

    public void setTrialVariable(String trialVariable) {
        this.trialVariable = trialVariable;
    }

    public String getTrialResult() {
        return trialResult;
    }

    public void setTrialResult(String trialResult) {
        this.trialResult = trialResult;
    }
}
  • 除了 @Ignore 的构造函数(为方便起见)以外,没有什么特别的

Dao.java(为方便起见组合)

public interface Dao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long[] insertExperiments(Experiment... experiments);

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long insertExperiment(Experiment experiment);

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long[] insertTrials(Trial... trials);

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long insertTrial(Trial trial);

    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateExperiments(Experiment... experiments);

    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateExperiment(Experiment experiment);

    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateTrials(Trial... trials);

    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateTrial(Trial trial);

    @Delete
    int deleteExperiments(Experiment... experiments);

    @Delete
    int deleteExperiment(Experiment experiment);

    @Delete
    int deleteTrials(Trial... trials);

    @Delete
    int deleteTrial(Trial trial);

    @Query("SELECT * FROM Experiment")
    List<Experiment> getAllexperiments();

    @Query("SELECT * FROM Experiment WHERE experimentDate BETWEEN :startdate AND :enddate")
    List<Experiment> getExperimentsInDateRange(String startdate, String enddate);

    @Query("SELECT * FROM Trial")
    List<Trial> getAllTrials();

    @Query("SELECT * FROM Experiment JOIN Trial ON parentExperiment = experimentId")
    List<TrialWithExperiment> getExperimentsWithTrials();


    public class TrialWithExperiment {
        private long experimentId;
        private String experimentName;
        private String experimentDate;
        private long trialId;
        private String trialVariable;
        private String trialResult;

        public long getExperimentId() {
            return experimentId;
        }

        public void setExperimentId(long experimentId) {
            this.experimentId = experimentId;
        }

        public String getExperimentName() {
            return experimentName;
        }

        public void setExperimentName(String experimentName) {
            this.experimentName = experimentName;
        }

        public String getExperimentDate() {
            return experimentDate;
        }

        public void setExperimentDate(String experimentDate) {
            this.experimentDate = experimentDate;
        }

        public void setTrialId(long trialId) {
            this.trialId = trialId;
        }

        public long getTrialId() {
            return trialId;
        }

        public String getTrialVariable() {
            return trialVariable;
        }

        public void setTrialVariable(String trialVariable) {
            this.trialVariable = trialVariable;
        }

        public String getTrialResult() {
            return trialResult;
        }

        public void setTrialResult(String trialResult) {
            this.trialResult = trialResult;
        }
    }
}
  • 请注意 TrialWithExperiment 类,该类定义了Trial及其拥有实验的组合。
  • 请注意列名如何区分,例如不仅是id,而且 experimentId trialId 可以区分它们。
  • 请注意最后一个@Query getExperimentsWithTrials(),这将返回带有试验的试验列表。

@Database ExperimentDatabase.java

@Database(entities = {Experiment.class, Trial.class}, version = 1,exportSchema = false)
public abstract class ExperimentDatabase extends RoomDatabase {
    public abstract Dao getDao();
} 

最后一项利用以上内容的活动:-

public class MainActivity extends AppCompatActivity {

    ExperimentDatabase mDB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDB = Room.databaseBuilder(this,ExperimentDatabase.class,"experimentdb").allowMainThreadQueries().build();
        mDB.getDao().insertExperiments(new Experiment[]{
                new Experiment("Experiment 1","2019-01-01"),
                new Experiment("Experiment 2", "2019-02-01")
        });
        List<Experiment> experiments = mDB.getDao().getExperimentsInDateRange("2019-01-01","2019-12-31");
        for (Experiment e: experiments) {
            Log.d("EXPERIMENTS", "Experiment is " + e.getExperimentName() + " on " + e.getExperimentDate());
        }

        experiments = mDB.getDao().getAllexperiments();
        for (Experiment e: experiments) {
            Log.d("EXPERIMENTS", "Experiment is " + e.getExperimentName() + " on " + e.getExperimentDate());
        }

        for (Experiment e: experiments) {
            mDB.getDao().insertTrial(
                    new Trial(
                            e.getExperimentId(),
                            "Variable for " + e.getExperimentName(),
                            "Result for Experiment on " + e.getExperimentDate()
                    )
            );
        }

        List<Trial> trials = mDB.getDao().getAllTrials();
        for (Trial t: trials ) {
            Log.d("TRIAL ",
                    "Trial is for ExperimentID " + String.valueOf(t.getParentExperiment()) +
                            "\n\tVariable = " + t.getTrialVariable() +
                            "Result = " + t.getTrialResult()
            );
        }


        List<Dao.TrialWithExperiment> trialsWithExperiments = mDB.getDao().getExperimentsWithTrials();

        for (Dao.TrialWithExperiment te:trialsWithExperiments) {
            Log.d(
                    "TRIALWITHEXPERIMENT",
                    "Experiment Name = " + te.getExperimentName() +
                            "\n\tExperiment Date = " + te.getExperimentDate() +
                            "\n\t\tTrial Variable = " + te.getTrialVariable() +
                            "\n\t\tTrial Result = " + te.getTrialResult()
            );

        }
    }
}

此:-

  • 添加2个实验(每次运行)
  • 检索日期范围内的实验(假定采用SQLite认可的日期格式),并将其输出到日志中。
  • 检索所有实验并将其输出到日志中。
  • 使用实验列表为每个实验添加一个试验。
  • 检索所有试用版并将其输出到日志中。
  • 与父实验一起检索所有试验,并将它们输出到日志中。

结果

05-28 10:19:42.770 5750-5750/? D/EXPERIMENTS: Experiment is Experiment 1 on 2019-01-01
05-28 10:19:42.770 5750-5750/? D/EXPERIMENTS: Experiment is Experiment 2 on 2019-02-01
05-28 10:19:42.776 5750-5750/? D/EXPERIMENTS: Experiment is Experiment 1 on 2019-01-01
05-28 10:19:42.776 5750-5750/? D/EXPERIMENTS: Experiment is Experiment 2 on 2019-02-01
05-28 10:19:42.786 5750-5750/? D/TRIAL: Trial is for ExperimentID 1
      Variable = Variable for Experiment 1Result = Result for Experiment on 2019-01-01
05-28 10:19:42.786 5750-5750/? D/TRIAL: Trial is for ExperimentID 2
      Variable = Variable for Experiment 2Result = Result for Experiment on 2019-02-01
05-28 10:19:42.787 5750-5750/? D/TRIALWITHEXPERIMENT: Experiment Name = Experiment 1
      Experiment Date = 2019-01-01
          Trial Variable = Variable for Experiment 1
          Trial Result = Result for Experiment on 2019-01-01
05-28 10:19:42.787 5750-5750/? D/TRIALWITHEXPERIMENT: Experiment Name = Experiment 2
      Experiment Date = 2019-02-01
          Trial Variable = Variable for Experiment 2
          Trial Result = Result for Experiment on 2019-02-01

替代/附加

另一种方法可能是利用 @Relation 在每个实验中创建一个对象,该对象包括该对象中相关/相关试验的列表。

在上面的内容上进行扩展,然后将以下内容添加到 Dao.java

@Query("SELECT * FROM  Experiment")
List<ExperimentWithTrials> getExperimentsAndTrials();

class ExperimentWithTrials {
    private long experimentId;
    private String experimentName;
    private String experimentDate;
    @Relation(parentColumn = "experimentId", entityColumn = "parentExperiment")
    List<Trial> trials;

    public long getExperimentId() {
        return experimentId;
    }

    public void setExperimentId(long experimentId) {
        this.experimentId = experimentId;
    }

    public String getExperimentName() {
        return experimentName;
    }

    public void setExperimentName(String experimentName) {
        this.experimentName = experimentName;
    }

    public String getExperimentDate() {
        return experimentDate;
    }

    public void setExperimentDate(String experimentDate) {
        this.experimentDate = experimentDate;
    }

    public List<Trial> getTrials() {
        return trials;
    }

    public void setTrials(List<Trial> trials) {
        this.trials = trials;
    }
}

,然后将以下内容添加到 MainActivity.java

    List<Dao.ExperimentWithTrials> experimentsWithTrials = mDB.getDao().getExperimentsAndTrials();
    for (Dao.ExperimentWithTrials et: experimentsWithTrials ) {
        Log.d(
                "EXPERIMENTANDTRIALS",
                "Experiment Name = " + et.getExperimentName() +
                        "\n\tExperiment Date = " + et.getExperimentDate()
        );
        for (Trial t: et.getTrials()) {
            Log.d(
                    "TRIALFOREXPERIMENT",
                    "\t\tVariable = " + t.getTrialVariable() +
                            "\n\t\tResult = " + t.getTrialResult()
            );
        }
    }
}
  • 请注意,如何通过遍历嵌入在 ExperimentWithTrials 对象中的Trials列表(而不是前一个实验和Trial组合数据的列表)来获得Trials。

  • >
    • 这可能是纯粹的面向对象方法。
    • 但是,SQLite明智的做法是,它似乎在运行多个查询,因此很繁琐/效率低下。一个获得实验,然后另一个获得每个实验的基础试验。

结果附加输出

05-28 13:05:35.052 6524-6524/? D/EXPERIMENTANDTRIALS: Experiment Name = Experiment 1
      Experiment Date = 2019-01-01
05-28 13:05:35.052 6524-6524/? D/TRIALFOREXPERIMENT:      Variable = Variable for Experiment 1
          Result = Result for Experiment on 2019-01-01
05-28 13:05:35.052 6524-6524/? D/EXPERIMENTANDTRIALS: Experiment Name = Experiment 2
      Experiment Date = 2019-02-01
05-28 13:05:35.052 6524-6524/? D/TRIALFOREXPERIMENT:      Variable = Variable for Experiment 2
          Result = Result for Experiment on 2019-02-01
  • 请注意,为方便起见,以上所有操作均在主线程上运行(即已使用 .allowMainThreadQueries())。如果遵循建议,则所有数据库访问都将通过另一个线程进行,在这种情况下,建议使用@Transaction批注进行查询。