简体   繁体   中英

Relationship Handling: Hibernate vs JDBC

Imagine I have a MySQL database with the 2 tables patient and medicine . I have displayed their columns below.

Patient

idPatient (int) (primary key)
first_name (varchar)
last_name (varchar)

Medicine

idMedicine (int) (primary key)
idPatient (int) (foreign key)
drug_name (varchar)

Please note that Medicine table does have the foriegn key of Patient table.

Now, if I use pure JDBC, I will do the following to create a bean for the Medicine and Patient tables

PatientBean class

public class PatientBean
{
    private int idPatient;
    private String first_name;
    private String last_name;

    public void setIdPatient(int idPatient)
    {
        this.idPatient = idPatient;
    }

    public int getIdPatient()
    {
        return idPatient;
    }

    public void setFirstName(String first_name)
    {
        this.first_name = first_name;
    }

    public String getFirstName()
    {
        return first_name;
    }

    public void setLastName(String last_name)
    {
        this.last_name = last_name;
    }

    public String getLastName()
    {
        return last_name;
    }

}

`MedicineBean` class

public class MedicineBean
{
    private int idMedicine;
    private int idPatient;
    private String drug_name;

    public void setIdMedicine(int idMedicine)
    {
        this.idMedicine = idMedicine;
    }

    public int getIdMedicine()
    {
        return idMedicine;
    }

    public void setIdPatient(int idPatient)
    {
        this.idPatient = idPatient;
    }

    public int getIdPatient()
    {
        return idPatient;
    }

    public void setDrugName(String drug_name)
    {
        this.drug_name = drug_name;
    }

    public String getDrugName()
    {
        return drug_name;
    }

}

However if I reverse engineer my database for hibernate using a tool like NetBeans which will generate the POJO files, mapping etc for Hibernate, I can expect something like below.

PatientBean class

public class PatientBean
    {
        private int idPatient;
        private String first_name;
        private String last_name;
    private MedicineBean medicineBean;

        public void setIdPatient(int idPatient)
        {
            this.idPatient = idPatient;
        }

        public int getIdPatient()
        {
            return idPatient;
        }

        public void setFirstName(String first_name)
        {
            this.first_name = first_name;
        }

        public String getFirstName()
        {
            return first_name;
        }

        public void setLastName(String last_name)
        {
            this.last_name = last_name;
        }

        public String getLastName()
        {
            return last_name;
        }

    public void setMedicineBean(String medicineBean)
        {
            this.medicineBean = medicineBean;
        }

        public String getMedicineBean()
        {
            return medicineBean;
        }
    }

MedicineBean class

public class MedicineBean
    {
        private int idMedicine;
        private int idPatient;
        private String drug_name;
    private Set<PatientBean> patients = new HashSet<PatientBean>(0);

        public void setIdMedicine(int idMedicine)
        {
            this.idMedicine = idMedicine;
        }

        public int getIdMedicine()
        {
            return idMedicine;
        }

        public void setIdPatient(int idPatient)
        {
            this.idPatient = idPatient;
        }

        public int getIdPatient()
        {
            return idPatient;
        }

        public void setDrugName(String drug_name)
        {
            this.drug_name = drug_name;
        }

        public String getDrugName()
        {
            return drug_name;
        }

    public void setPatients(Set<PatientBean>patients)
    {
        this.patients = patients;
    }

    public Set<PatientBean> getPatients()
    {
        return patients;
    }

    }

Not only this, Hibernate will also map the relationship type (one to one, one to many, many to one) inside the xml files. However in JDBC we don't care about them at all, they are just foreign keys treated in same way.

So my question is, why is this difference? I believe most of the operations Hibernate does are useless and just using CPU. For an example, trying to retrieve the list of patients in Patient table when we call getAllMedicines() method. In 99% of the case we just need all medicines not the list of patients, if we need that we can make a join and get it!

So what is the reason behind this? Or else should we maintain the same behavior for JDBC too?

I don't think that with hibernate you lose the full control as you are afraid.

The main difference is that hibernate will add an extra layer between your code and jdbc. This layer can be really thin : you have the choice to use jdbc in hibernate at anytime . So you are not losing any control.

The harder part is to understand how hibernate works so that you can use its higher level api and know how hibernate will translate that to jdbc. This is a bit a complex task, because orm mapping is a complex subject. Reading several times the reference documentation, to know exactly what hibernate can do, and what they recommend to do and not do, is a good starting point. The remaining will come from experience using hibernate.

For your example, you say hibernate map relationship, but this is not the case : your reverse-engineering tool did it. You are free to not map a relationship and map instead just the foreign key basic type (like a Long if the id is a number).

As for the loading of stuff. If you wish to always have a @OneToMany loaded, just annotate it with FetchType.EAGER . @*ToMany associations are lazy by default (to avoid loading too many data), but on the other hand, @*ToOne assocation are EAGER by default.

This can be configured at the entity level, making it the default behavior for queries, but can be overloaded for each query.

You see ? You are not losing control, you just need to understand how the hibernate api translate to jdbc.

Apart from bugs, which are fixed when raised to the hibernate team, the performance impact of hibernate is not that much. And in performance critical part of the application, you always have the choice to resort to jdbc, where the hibernate overhead is 0.

What do you gain from using hibernate ? From my experience, refactoring in entity model / database model is much easier, because you change the hibernate mapping, and all the queries generated by hibernate are automatically changed too. You just have to update the custom queries (SQL / HQL / Criteria) that you've hand-written.

From my experience (10 years using hibernate) on a several hundred tables (some of them with more than 10B rows), several terabytes database, i would not want to go back to plain jdbc, which does not mean i don't use it when it is the perfect tool, but it is just like 1 or 2% of the orm code i write.

Hope that helps.

EDIT: and if you are using hibernate with spring, have a look at spring-jdbc which adds a nice layer around jdbc. There, you nearly doesn't need to read the doc: you recognize directly how it will be translated to jdbc, but it brings lots of utility that reduce a lot the boilerplate of using jdbc directly (like exception handling to close Resultset and PreparedStatement , transformation of ResultSet to List of DTO, etc.).

Of course hibernate and spring-jdbc can be used in the same application. They just have to be configured to use the same transaction layer, and care be taken when used in the same tx.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM