hibernate注解:总结

hibernate关系梳理以及心得总结

hibernate是什么?为什么要用hibernate?或许问题不该这么问,应该如是说,如果我用hibernate将会带来什么改变,什么情况下可以用,什么情况下比较好用,什么情况下就不能用。
  • 曾经有一个人说,如果你不能简单的将事物说明白,那你自己也不是真的懂。
  • 在我的想法中我不敢苟同,很多事我们都尝试以简单的语言去解释,但很多事并不能如我们的愿,谁可以夸下海口说自己真的懂,那我只能说你真不懂。
  • 此些hibernate文章大多都是试验得出结论,然后拿来使用,我并不求可以将hibernate说明白,只是学以致用,且主要在用。
hibernate改变了原有对数据库的操作。
  • java中操作数据库,实现crud,一开始我们都是从jdbc用起。自己写sql,然后执行sql,将返回结果封装。
  • hibernate封装了简单的sql语句,并将返回结果自动orm到了java对象。此时我们根据主键查询也只需要调用findOne()方法即可,添加操作也只需save()一下。
  • hibernate此种做法,有利有弊,对于一般的业务,将会变得简便,但是对于复杂业务则没有纯sql灵活。
  • 我自己的想法,比较常见的业务,两个表连表查询,虽然hibernate支持原生sql和自己的hql语句,但我觉得hibernate的主旨是让不懂sql的后端程序员也能处理数据,它最想要的做法不是再写join这些语句,而是直接从一个对象身上get到它的相关对象,所以就产生了简单的关系映射。
hibernate的关系映射也无外乎数据库中的那几个关系
  • @OneToOne,一对一
  • @OneToMany,一对多
  • @ManyToOne,多对一
  • @ManyToMany,多对多
  • 干脆就是独立的,和谁都没有关系

关系都是双向的,现实生活中是,但是在代码里不是,你可以人为的设定从一方可以找到另一方,但是从另一方不能找到这一方。做法很简单,你可以在A类中写一个成员属性b,类型为B类,但是在B类中不写类型为A的成员属性。
从实际出发,在设计javaBean的时候,就得理清楚关系,考虑好单双向和共生性。

@OneToOne
  • 一对一关系,不仅存在着双向性,还存在着共生性。但是设计时还是有套路可循的。
  • @OneToOne注解的cascade属性,可以直接设置CascadeType.MERGE和CascadeType.REFRESH,级联更新和级联刷新,不会产生多余的影响。
  • @OneToOne注解的fetch属性,默认值为FetchType.EAGER急加载。即如果A中由B类型的成员属性,那么在查询A的同时把对应的B也查询出来,因为是一对一,一个A只有一个B,急加载并无多大影响。
  • 双向性,如果只有一方的类中有另一方类型的成员属性,则为单向。如果双方的类中互相包含对方类型的成员属性,则为双向。
  • @OneToOne的mappedBy属性与@JoinColumn注解,成对出现且互斥,即mappedBy出现在A类中,@JoinColumn只能出现在B类中。
    如果是双向性,但是没有使用mappedBy属性与@JoinColumn注解,则在自动生成的两个表中都包含对方的外键,且形成了循环外键。
    最好的做法还是将关系设计成双向性且配合mappedBy属性与@JoinColumn注解。mappedBy的意思是在本类对应的表中我不要外键,@JoinColumn的意思是在我这个类对应的表里要有外键。mappedBy的取值为对方类中被@JoinColumn修饰的成员属性。
  • 共生性,因为一对一的特殊性质,所以可以讨论共生性,共生性涉及到级联添加和级联删除。即A与B同时添加,A与B同时删除。@OneToOne注解的cascade属性中设置CascadeType.PERSIST和CascadeType.REMOVE。
public class A {
    @OneToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
    @JoinColumn(name="b_id")
    private B b;
}

public class B {
    @OneToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}, mappedBy="b")
    private A a;
}

//看情况设置CascadeType.PERSIST和CascadeType.REMOVE
@OneToMany和@ManyToOne
  • 一对多和多对一关系是成对出现的,从一方出发是一对多,那么从对方出发就是多对一。但是注解可以单独使用。
  • 单独使用@OneToMany和@ManyToOne时,设置@JoinColumn都会在多的那方生成外键,这点就很奇怪。
  • 同上,不管是@OneToMany还是@ManyToOne,都可以直接设置CascadeType.MERGE和CascadeType.REFRESH。
  • @ManyToOne是急加载,@OneToMany是懒加载。即查询一的一方不会把它所有的多的一方一起查出,因为会影响效率。而查询多的一方会把一方一起查出,因为只有一个所以不怎么影响。
  • 最好的做法还是将关系设计成双向性且配合mappedBy属性与@JoinColumn注解。
  • 一对多关系仍然有可能涉及共生性,即删除了一的一方之后,多的一方需不需要一起删除,创建了多的一方那一的一方需不需要一起被创建。
    建议的做法是考虑删除即可。在代码中保证如果要创建多的一方那必须先存在一的一方,然后就不考虑创建的时候得共生问题。
public class A {
    @OneToMany(cascade={CascadeType.MERGE, CascadeType.REFRESH}, mappedBy="a")
    private List<B> b;
}

public class B {
    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
    @JoinColumn(name="a_id")
    private A a;
}

//看情况在A类中设置CascadeType.REMOVE
@ManyToMany
  • 多对多的关系就不用考虑双向性,因为你不双向,就等于自断一臂,只能从一方来维护关系不是很方便。
  • 多对多的关系也不用考虑共生性,因为你不可能级联添加和级联删除,因为不管是哪方,都能看做是一的一方也都能看做是多的一方。如果你要级联添加,你可以把要添加的数据看做是一的一方,就没必要级联添加了。如果你要删除,那么把要删除的数据看做是多的一方,也没必要级联删除了。
  • 上来直接设置CascadeType.MERGE和CascadeType.REFRESH,且只设置这两个值。
  • mappedBy和@JoinColumn也不需要了,因为我们在数据库层面使用的是中间表。
  • @JoinTable(name=”“, joinColumns=@JoinColumn(name=”“), inverseJoinColumns=@JoinColumn(name=”“)),该注解用于创建中间表,指定本类在该表中的外键和对方在该表中的外键。
    可以在两个类中都使用这个注解,也可以在一个类中使用,另一个类中mappedBy
public class A {
    @ManyToMany(cascade={CascadeType.MERGE, CascadeType.REFRESH})
    @JoinTable(name="a_b", joinColumns=@JoinColumn(name="a_id"), inverseJoinColumns=@JoinColumn(name="b_id"))
    private List<B> b;
}

public class B {
    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
    @JoinTable(name="a_b", joinColumns=@JoinColumn(name="b_id"), inverseJoinColumns=@JoinColumn(name="a_id"))
    private List<A> a;

    /*
    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}, mappedBy="b")
    private List<A> a;
    */
}

感谢你们看我叨逼叨这么久,如果有纰漏请指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值