关系处理:Hibernate与JDBC

时间:2016-09-23 06:04:28

标签: java mysql database hibernate jdbc

想象一下,我有一个包含2个表patientmedicine的MySQL数据库。我在下面显示了他们的专栏。

病人

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

医学

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

请注意,Medicine表的{for}关键字为Patient

现在,如果我使用纯JDBC,我将执行以下操作为MedicinePatient表创建一个bean

PatientBean课程

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;
    }

}

但是,如果我使用像NetBeans这样的工具对hibernate进行逆向工程,它会为Hibernate生成POJO文件,映射等,我可以期待下面的内容。

PatientBean课程

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课程

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;
    }

    }

不仅如此,Hibernate还会在xml文件中映射关系类型(一对一,一对多,多对一)。但是在JDBC中我们根本不关心它们,它们只是以同样方式处理的外键。

所以我的问题是,为什么这有区别?我相信Hibernate所做的大多数操作都是无用的,只是使用CPU。例如,当我们调用patients方法时,尝试检索Patient表中的getAllMedicines()列表。在99%的情况下,我们只需要所有药物而不是患者名单,如果我们需要,我们可以加入并获得它!

那背后的原因是什么?或者我们也应该为JDBC保持相同的行为吗?

1 个答案:

答案 0 :(得分:0)

我不认为在休眠时你会因为害怕而失去完全的控制权。

主要区别在于hibernate会在你的代码和jdbc之间添加一个额外的层。这个层可以很薄:你可以随时选择在hibernate 中使用jdbc 。所以你没有失去任何控制。

更难的部分是了解hibernate如何工作,以便您可以使用其更高级别的api并知道hibernate将如何将其转换为jdbc。这有点复杂,因为orm映射是一个复杂的主题。多次阅读参考文档,确切了解hibernate可以做什么,以及他们建议做什么和不做什么,都是一个很好的起点。剩下的将来自使用hibernate的经验。

对于你的例子,你说hibernate地图关系,但事实并非如此:你的逆向工程工具做到了。您可以自由地不映射关系和映射而只是映射外键基本类型(如果id是数字,则为Long)。

关于东西的装载。如果您希望始终加载@OneToMany,只需使用FetchType.EAGER进行注释即可。默认情况下,@*ToMany关联是惰性的(以避免加载太多数据),但另一方面,@*ToOne关联默认为EAGER

这可以在实体级别配置,使其成为查询的默认行为,但可以为每个查询重载。

你知道吗?你不会失去控制,你只需要了解hibernate api如何转换为jdbc。

除了在提升到hibernate团队时修复的bug之外,hibernate对性能的影响并不大。在应用程序的性能关键部分,您始终可以选择使用jdbc,其中hibernate开销为0.

使用hibernate可以获得什么?根据我的经验,重构实体模型/数据库模型要容易得多,因为你改变了hibernate映射,而hibernate生成的所有查询也会自动改变。您只需更新您手写的自定义查询(SQL / HQL / Criteria)。

根据我的经验(使用hibernate 10年)在数百个表(其中一些超过10B行),数TB的数据库,我不想回到普通的jdbc,这并不意味着我不要当它是完美的工具时使用它,但它就像我编写的orm代码的1%或2%。

希望有所帮助。

编辑:如果你正在使用spring的hibernate,请看一下spring-jdbc,它在jdbc周围增加了一个很好的层。在那里,你几乎不需要阅读文档:你直接认识到如何将它转换为jdbc,但它带来了许多实用工具,可以减少很多直接使用jdbc的样板(比如关闭{{1}的异常处理}和Resultset,将PreparedStatement转换为DTO列表等。)

当然,hibernate和spring-jdbc可以在同一个应用程序中使用。它们只需配置为使用相同的事务层,并且在同一个tx中使用时要小心。