java - 检查 Android 中的子 Firebase 数据库中是否存在值

标签 java android firebase firebase-realtime-database

我正在使用 Java 和 Firebase 为大学项目开发​​ Android 应用程序。我想根据他们的职位存储在大学工作的教员的详细信息,如姓名、电子邮件、部门等。我在院系内创建了 3 个子节点 HOD、类(class)导师和讲师,您可以在此处看到。

enter image description here

我的问题是,当我想在这些子项中的任何一个中添加成员时,我想检查该成员的电子邮件 ID 是否存在于任何其他子项中。例如,我想在 HOD 子项中添加一个成员。如果此成员电子邮件存在于 Lecturers 子项中,则应显示 Toast 用户已作为讲师存在,否则应在 Lecturer 中添加成员。

我使用了这段代码。

post = "HOD";
    databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        if (dataSnapshot.exists()){
            Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
        } else {
            post = "Class mentor";
            databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    if (dataSnapshot.exists()){
                        Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
                    } else {
                        post = "Lecturer";
                        databaseReference.child(post).orderByChild("email").equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                if (dataSnapshot.exists()){
                                    Toast.makeText(MainActivityAddFaculty.this, "User already exist in "+post, Toast.LENGTH_SHORT).show();
                                } else {
                                    checkData();
                                }
                            }

                            @Override
                            public void onCancelled(@NonNull DatabaseError databaseError) {
                                Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });

        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Toast.makeText(MainActivityAddFaculty.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
    }
});

它工作正常,但它很长,而且需要时间检查。如果有任何更好的解决方案,将会非常有帮助。

这是我添加院系的完整代码。

public class MainActivityAddFaculty extends AppCompatActivity {
    private TextInputLayout addName, addEmail;
    private TextInputEditText addEditName, addEditEmail;
    private Button addBtn;

    private Spinner addPositionSpinner,addDeptSpinner,addYearSpinner;
    private TextView addPosition,addDept,addYear;

    private String sDept = "Select department",sPost = "Select position",sYear = "Select year";
    private String position,department,year,post;
    private boolean b = false;

    private FirebaseDatabase firebaseDatabase;
    private FirebaseStorage firebaseStorage;
    private DatabaseReference databaseReference,databaseReference2;
    private StorageReference storageReference;
    LoadingDialog loadingDialog;

    private String facultyID;
    private String name,email;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_faculty);
        setTitle("Add Hod");

        assert getSupportActionBar() != null;
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        addName = findViewById(R.id.addFName);
        addEmail = findViewById(R.id.addFEmail);
        addEditName = findViewById(R.id.addFEditName);
        addEditEmail = findViewById(R.id.addFEditEmail);
        addBtn = findViewById(R.id.addFBtn);

        addPositionSpinner = findViewById(R.id.addFPositionSpinner);
        addPosition = findViewById(R.id.addFPosition);
        addDeptSpinner = findViewById(R.id.addFDepartmentSpinner);
        addDept = findViewById(R.id.addFDepartment);
        addYearSpinner = findViewById(R.id.addFYearSpinner);
        addYear = findViewById(R.id.addFYear);

        addDeptSpinner.setVisibility(View.GONE);
        addYearSpinner.setVisibility(View.GONE);
        addDept.setVisibility(View.GONE);
        addYear.setVisibility(View.GONE);

        firebaseDatabase = FirebaseDatabase.getInstance();
        databaseReference = firebaseDatabase.getReference("FACULTIES");

        facultyID = databaseReference.push().getKey();

        loadingDialog = new LoadingDialog(MainActivityAddFaculty.this);
        //selectPosition();

        //TODO:Select position
        List<String> categories = new ArrayList<>();
        categories.add(0,"Select position");
        categories.add("HOD");
        categories.add("Class mentor");
        categories.add("Lecturer");

        ArrayAdapter<String> dataAdapter;
        dataAdapter = new  ArrayAdapter(this,android.R.layout.simple_spinner_item,categories);

        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        addPositionSpinner.setAdapter(dataAdapter);
        addPositionSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                addPosition.setText(parent.getSelectedItem().toString());
                test();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                Toast.makeText(MainActivityAddFaculty.this, "Select a position", Toast.LENGTH_SHORT).show();
            }
        });


        addBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                name = addEditName.getText().toString().trim();
                email = addEditEmail.getText().toString().trim();

                if (TextUtils.isEmpty(name)) {
                    Toast.makeText(MainActivityAddFaculty.this, "Enter name", Toast.LENGTH_SHORT).show();
                }else  {
                    if (TextUtils.isEmpty(email)) {
                        Toast.makeText(MainActivityAddFaculty.this, "Enter email.", Toast.LENGTH_SHORT).show();
                    } else {
                        checkData();
                    }
                }
            }
        });
    }

    private void test(){
        position = addPositionSpinner.getSelectedItem().toString();

        if (position.equals(sPost)){
            addDeptSpinner.setVisibility(View.GONE);
            addYearSpinner.setVisibility(View.GONE);
            addDept.setVisibility(View.GONE);
            addYear.setVisibility(View.GONE);
        }else if (position.equals("HOD")){
            addDeptSpinner.setVisibility(View.VISIBLE);
            addYearSpinner.setVisibility(View.GONE);
            addDept.setVisibility(View.VISIBLE);
            addYear.setVisibility(View.GONE);
        } else if (position.equals("Class mentor")){
            addDeptSpinner.setVisibility(View.VISIBLE);
            addDept.setVisibility(View.VISIBLE);
            addYearSpinner.setVisibility(View.VISIBLE);
            addYear.setVisibility(View.VISIBLE);
        } else if (position.equals("Lecturer")){
            addDeptSpinner.setVisibility(View.GONE);
            addYearSpinner.setVisibility(View.GONE);
            addDept.setVisibility(View.GONE);
            addYear.setVisibility(View.GONE);
        } else {
            addDeptSpinner.setVisibility(View.GONE);
            addYearSpinner.setVisibility(View.GONE);
            addDept.setVisibility(View.GONE);
            addYear.setVisibility(View.GONE);
        }
}

    private void checkData(){
        position = addPositionSpinner.getSelectedItem().toString();
        department = addDeptSpinner.getSelectedItem().toString();
        year = addYearSpinner.getSelectedItem().toString();

        if (position.equals(sPost)){
            Toast.makeText(this, "Select position", Toast.LENGTH_SHORT).show();
        } else if (position.equals("HOD")){
                        if (department.equals(sDept)){
                            Toast.makeText(MainActivityAddFaculty.this, "Select department.", Toast.LENGTH_SHORT).show();
                        } else {
                            AddHOD addHOD = new AddHOD(name,position,department,email,facultyID);
                            databaseReference.child(position).child(facultyID).setValue(addHOD).addOnSuccessListener(new OnSuccessListener<Void>() {
                                @Override
                                public void onSuccess(Void aVoid) {
                                    Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
                                }
                            }).addOnFailureListener(new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception e) {
                                    Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
        }else if (position.equals("Class mentor")){
                //add Class mentor process started
                if (!department.equals(sDept)){
                    if (!year.equals(sYear)) {
                        AddClassMentor addClassMentor = new AddClassMentor(name, position, department, year, email, facultyID);
                        databaseReference.child(position).child(facultyID).setValue(addClassMentor).addOnSuccessListener(new OnSuccessListener<Void>() {
                            @Override
                            public void onSuccess(Void aVoid) {
                                Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        });
                    }else {
                        Toast.makeText(this, "Select year.", Toast.LENGTH_SHORT).show();
                    }
                    } else {
                    Toast.makeText(this, "Select department", Toast.LENGTH_SHORT).show();
                    }
        } else if (position.equals("Lecturer")){
            AddLecturer addLecturer = new AddLecturer(name,position,email,facultyID);
            databaseReference.child(position).child(facultyID).setValue(addLecturer).addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    Toast.makeText(MainActivityAddFaculty.this, "Faculty added successfully", Toast.LENGTH_SHORT).show();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(MainActivityAddFaculty.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
        } else {
            Toast.makeText(this, "Entry is pending.", Toast.LENGTH_SHORT).show();
        }
    }
}

最佳答案

Firebase 的查询适用于节点列表。由于您有一个层次结构,因此您需要为其中的每个列表触发相同的查询,就像您今天所做的那样。

与往常一样,在处理 NoSQL 数据库时,解决方案是以一种使用例最简单的方式对数据进行建模。如果您想搜索所有成员,请存储单个成员列表:

"members": {
  "$memberid": {
    "email": "membersemail@institute.edu",
    "memberType": "Class mentor" // or "HOD" or "Lecturer"
  }
}

使用上述结构,您只需执行一个查询即可查找具有特定电子邮件地址的所有成员。

<小时/>

您可以使用上述结构来替换您当前拥有的三个结构,或者您可以将其用作仅用于此用例的附加结构。选择哪一种取决于您应用中的其他用例,没有一种解决方案适合所有应用,只有适合您的解决方案。

<小时/>

像您在这里所做的那样在值之间强制执行唯一性,随着时间的推移将导致可扩展性问题,因为您:

  1. 需要搜索所有成员,随着成员数量的增加,这会花费更多时间。
  2. 更重要的是:您需要使用事务来插入新用户,以减少多个用户同时声明同一电子邮件地址的可能性。
  3. 这会导致第二个扩展问题,因为您需要在不断增长的 /members 节点上运行该事务。
  4. 最后:恶意用户可以通过编写自己的代码来绕过交易,并仍然声称拥有任何电子邮件地址。

只有当您使用这些值作为列表中的键时,才能真正强制执行 Firebase 上的唯一性,因此需要维护一个(附加)电子邮件地址列表。

有关此内容的更多信息,请参阅:

关于java - 检查 Android 中的子 Firebase 数据库中是否存在值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61710479/

相关文章:

java - Spring 用户忘记密码替代方法

ios - 尝试使用 Firebase 动态链接,无法在 iOS 上打开应用

java - Android 和 JFileChooser

java - 代号“一个动画麻烦”(也在纸牌演示中)?

java - 同一 Java 类的两个版本,每个版本都有不同的父类(super class)

php - Json 使用 WHERE column = $variable 读取 mysql 列

javascript - 在 Firebase Cloud Functions 中使用异步/等待时返回 promise

swift - Firebase 查询无法快速运行没有结果

java - 为什么在 Java 中将文件读入内存需要 4 倍的内存?

java, generics - 如何参数化一个类型为 T 的类,这两个类型都是 : extends and implements sth