SQLite
 sql >> Base de données >  >> RDS >> SQLite

Associer des tables à l'aide de la base de données Room dans Android Studio

Je crois que l'exemple de travail suivant est l'un des moyens par lesquels vous pouvez réaliser ce que vous voulez.

Le code

L'entité expérimentale (table) 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;
    }
}
  • Rien de spécial sauf peut-être le @Ignore 'd constructeur (pour plus de commodité)

L'entité d'essai 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;
    }
}
  • Rien de spécial sauf peut-être le @Ignore 'd constructeur (pour plus de commodité)

Dao.java (combiné pour plus de commodité)

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;
        }
    }
}
  • Notez l'essai avec expérience classe, cela définit une combinaison d'un essai et de son expérience propriétaire.
  • Notez comment les noms de colonne sont distincts, par exemple. pas seulement d'identifiant mais experimentId et trialId les différencie.
  • Notez la dernière @Query getExperimentsWithTrials() cela renverra une liste d'essais avec leurs expériences.

@Database ExperimentDatabase.java

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

Enfin une activité qui utilise ce qui précède :-

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()
            );

        }
    }
}

Ceci :-

  • Ajoute 2 tests (à chaque exécution)
  • Récupère les expériences dans une plage de dates (cela suppose un format de date reconnu par SQLite) et les affiche dans le journal.
  • Récupère toutes les expériences et les enregistre dans le journal.
  • Utilise la liste des expériences pour ajouter un essai à chaque expérience.
  • Récupère tous les essais et les enregistre dans le journal.
  • Récupère tous les essais avec l'expérience parente et les enregistre dans le journal.

Le résultat

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

Alternative/Complémentaire

Une autre approche pourrait être d'utiliser @Relation pour créer un objet par expérience qui inclut une liste des essais liés/associés dans cet objet.

En développant ce qui précède, les éléments suivants pourraient être ajoutés à 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;
    }
}

puis les éléments suivants pourraient être ajoutés à 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()
            );
        }
    }
}
  • Notez comment les essais sont obtenus via la boucle dans la liste des essais intégrés avec ExperimentWithTrials objet, par opposition à la liste des données d'expérience et d'essai combinées de la précédente.

    • C'est probablement une manière OO plus pure.
    • Cependant, en ce qui concerne SQLite, cela semble fastidieux/inefficace car il semble exécuter plusieurs requêtes. Un pour obtenir les expériences, puis un autre pour obtenir les essais sous-jacents pour chaque expérience.

Sortie supplémentaire résultante

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
  • Notez que pour plus de commodité, tout ce qui précède a été exécuté sur le thread principal (c'est-à-dire .allowMainThreadQueries() a été utilisé). Si vous suivez les recommandations, tout l'accès à la base de données se fera via un autre thread, auquel cas l'annotation @Transaction est conseillée pour les requêtes.