hibernate的懒加载、各类关系以及annotation

hibernate:get和load方法

代码执行到session.load(User.class,Id)并不执行SQL语句,而且通过get方法可以获取到Id的值,不管Id的值在数据库表中是否存在,且不执行SQL语句。

 

session.get(User.class,Id)则不一样,代码执行到这一行就会执行一条SQL查询语句,而且Id的值在数据库表中一定存在。网上有说get方法返回的一定是实体类,但是也有说是可能为代理对象。我比较赞成后者,通过代码也能看出来。

User user = (User) session.load(User.class, 11);

            user.setUser_name("heihei");

            Useru=(User)session.get(User.class, 11);

            System.out.println(u.getUser_name());

数据库表中Id为11的用户名为haha,通过get方法获取的却是heihei,且后台数据库表中数据并没有改变。没执行update操作。

 

load、get查找数据是有一定的顺序的,各级缓存什么的。暂时没看到缓存这一块,不做记录,以后回头再做修改。

 

 

many2one单向:

add:

1、 先添加多one

例:ClassRoom cr=new ClassRoom();

   cr.setName(“C”);

   session.save(cr);

   Stu stu=new Stu();

   stu.setName(“clover”);

   stu.setCla(cr);

   session.save(stu);

这种情况,会执行两条插入SQL语句。

2、 先添加多

例: Stu stu=new Stu();

stu.setName(“clover”);

   session.save(stu);

     ClassRoomcr=new ClassRoom();

     cr.setName(“C++”);

     session.save(cr);

     stu.setCla(cr);//stu为persistent状态

这种情况,执行的SQL比较多,两条插入语句一条更新语句。

3、 错误的情况

例: ClassRoom cr = new ClassRoom();

     cr.setName(“Java”);

     Stu stu = newStu();

     stu.setName(“haha”);

     session.save(stu);

stu.set(cr);

cr对象当前为transient,而stu已经转化为persistent状态。是不能这样做的。

异常信息:org.hibernate.TransientObjectException

 

load:

1、 one

先加载one,最后查询到的结果只能看到one。不能看到many的数据信息。

2、 many

先加载many,则可以通过关联字段查询到one的数据。而且many一方的数据具有懒加载的特性。

 

update:

更新什么的应该不会更新外键,所以不再说明。

 

delete:

肯定可以删除多的一方,不能删除one的一方。

 

many2one配置文件:

<hibernate-mappingpackage="been">

    <classname="Student" table="tb_stu">

        <idname="id">

            <generatorclass="native"></generator>

        </id>

        <propertyname="name" />

        <many-to-one name="cla" column="cid"cascade="all/delete/update"/>

    </class>

</hibernate-mapping>

 

cascade:级联操作

删除操作室,级联操作不建议在many一方使用,因为many可能不是一条数据。在删除stu的时候,会级联删除Cla,而此时stu中还有别的数据关联cla此时就是报错。

 

many2one单向:

和one2many相反,不同的地方在于配置文件和代码:

配置文件:

<set name="comments"lazy="extra">

            <keycolumn="cid" />

            <one-to-manyclass="Comment" />

</set>

代码不同的地方,在于处理many的变量需要使用集合。所以对应的配置文件也发生变化。

需要说明的地方在于lazy:

lazy=”true”:懒加载,需要加载第二条SQL的时候才会加载;

lazy=”false”:不会懒加载;

lazy=”extra”:根据需要使用不同的SQL语句。比如查询留言下有多少评论,使用extra属性则会通过count查找。

 

one2many双向,就是one2many单向与many2one单向合在一起,就像齿轮相互咬合的感觉。

one2many单向和many2one单向使用的时候,维护关系只在一方。one2many双向则是通过任何一方都可以知道另外一方。

 

one2one单向和many2one单向很像,不同的地方在不one2one的关系是一对一的,不能多对一或者一对多。

配置文件:(维护关系的一方)

<hibernate-mappingpackage="been">

    <classname="IDCard" table="tb_card">

        <idname="id">

            <generatorclass="native"></generator>

        </id>

        <propertyname="no" />

        <many-to-onename="person" column="pid"unique="true"/>

    </class>

</hibernate-mapping>

 

one2one双向:和many2one很像,个人感觉。

配置文件,在one2one的基础之上:

<hibernate-mappingpackage="been">

    <classname="Person" table="tb_person">

        <idname="id">

            <generatorclass="native"></generator>

        </id>

        <propertyname="name" />

        <!--name指定属性的名称,property-ref指定维护关系的一方为对端 -->

        <one-to-onename="card" property-ref="person"/>

    </class>

</hibernate-mapping>

 

insert、update and delete 不再说。

load:很奇怪的地方,如果首先load关系被维护的一方,hibernate会自动关联两张表查询,通过person查询idcard也只有一条SQL。

        Personperson = (Person) session.load(Person.class, 1);

        System.out.println(person.getName());

        System.out.println(person.getCard().getId());

 

查询的SQL及结果:

Hibernate: select person0_.id asid6_1_, person0_.name as name6_1_, idcard1_.id as id5_0_, idcard1_.no asno5_0_, idcard1_.pid as pid5_0_ from tb_person person0_ left outer join tb_cardidcard1_ on person0_.id=idcard1_.pid where person0_.id=?

clover

1

如果load维护关系的一方,则是另外的一种情况:

IDCardid=(IDCard)session.load(IDCard.class, 1);

    System.out.println(id.getNo());

    System.out.println(id.getPerson().getName());

查询的SQL及结果:

Hibernate: select idcard0_.id asid5_0_, idcard0_.no as no5_0_, idcard0_.pid as pid5_0_ from tb_card idcard0_where idcard0_.id=?

123456

Hibernate: select person0_.id asid6_1_, person0_.name as name6_1_, idcard1_.id as id5_0_, idcard1_.no asno5_0_, idcard1_.pid as pid5_0_ from tb_person person0_ left outer join tb_cardidcard1_ on person0_.id=idcard1_.pid where person0_.id=?

Hibernate: select idcard0_.id asid5_0_, idcard0_.no as no5_0_, idcard0_.pid as pid5_0_ from tb_card idcard0_where idcard0_.pid=?

clover


 

many2many双向

直接上配置文件:

<hibernate-mappingpackage="been">

    <classname="Role" table="tb_role">

        <idname="id">

            <generatorclass="native"></generator>

        </id>

        <propertyname="name" />

        <setname="admins"table="tb_admin_role" lazy="extra">

            <keycolumn="rid" />

            <many-to-manyclass="Admin"column="aid" />

        </set>

    </class>

</hibernate-mapping>

 

<hibernate-mappingpackage="been">

    <classname="Admin"table="tb_adm">

        <idname="id">

            <generatorclass="native"></generator>

        </id>

        <propertyname="name" />

        <setname="roles" table="tb_admin_role"lazy="extra">

            <keycolumn="aid" />

            <many-to-manyclass="Role" column="rid" />

        </set>

    </class>

</hibernate-mapping>

 

至于单向,从任意一方删除的对应的属性就是了。



1、  增删改查

配置文件和原来使用xml不一样,不需要再配置xxx.hbm.xml文件,不过hibernate.cfg.xml文件需要之间指定实体类的路径:

<!-- 如果数据库表没有建立,会自动创建 -->

<propertyname="hibernate.hbm2ddl.auto">update</property>

<mapping class="been.User"/>

<mapping class="been.Cla"/>

<mappingclass="been.Student"/>

需要在类名前添加:

@Entity

@Table(name=”tb_user”)//指定表名

在对应的Id前添加:

@Id

@GeneratedValue

 

代码:

@Entity

@Table(name="tb_user")

public class User {

        private intaccount;

        private String user_name;

        @Id

        @GeneratedValue

        public int getAccount() {

            returnaccount;

        }

·······

}

2、 many2one

one的一方,在many方维护两者的关系:

@Entity

@Table(name = "tb_cla")

public class Cla {

        private intid;

        private String name;

        private Set<Student> stus;

        public Cla() {

            setStus(new HashSet<Student>());

        }

        @Id

        @GeneratedValue

        public intgetId() {

            return id;

        }

        //在many维护关系的字段

        @OneToMany(mappedBy="cla")

//查询数量的时候,可以智能使用count

        @LazyCollection(LazyCollectionOption.EXTRA)

        public Set<Student> getStus() {

            return stus;

    }

```````

}

many的一方:

@Entity

@Table(name = "tb_stu")

public class Student {

    private int id;

    private String name;

    private Cla cla;

    @Id

    @GeneratedValue

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    //启用懒加载的功能,懒加载添加在维护关系的一方

    @ManyToOne(fetch = FetchType.LAZY)

    //维护的关系的字段,外键

    //使用这个,many2one只会创建两个表,否则会自动创建一个中间表

    @JoinColumn(name = "cid")

    public Cla getCla() {

        return cla;

    }

    public void setCla(Cla cla) {

        this.cla = cla;

    }

    ····

}

 

3、  one2one

one2one和many2one很像,many2one或者one2many是一对多或者多对一的关系,而one2one可以使是这两者的特例,关系的两方都是一对一的关系。

代码:

 维护关系方:

package been;


import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;


@Entity
@Table(name = "tb_idCard")
public class IDCard {
private int id;
private String no;
private Person person;


@Id
@GeneratedValue
public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}


@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "pid")
public Person getPerson() {
return person;
}


public void setPerson(Person person) {
this.person = person;
}


public String getNo() {
return no;
}


public void setNo(String no) {
this.no = no;
}
}

被维护关系:

package been;


import javax.persistence.*;


@Entity
@Table(name = "tb_person")
public class Person {
private int id;
private String name;
private IDCard card;


@Id
@GeneratedValue
public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}

@OneToOne(mappedBy = "person")
public IDCard getCard() {
return card;
}


public void setCard(IDCard card) {
this.card = card;
}

public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}
}

4、  many2many

many2many和使用配置文件一样,一般使用两个many2one来实现。

 

 

 

 

PS:关于Id的想法,从学生的心理来说,在学校学习数据库的时候对已Id的想法是能不用就不用了,所以在hibernate刚接触的时候,感觉为啥非要用Id这个字段。特别是使用配置文件的时候,Id是必不可少的一个标签。在我工作的过程中,我也发现并不是每个表都有Id这个字段,但是主键却是必不可少的。这个Id,我想应该是封装hibernate的开发者,对经验的总结。我想,所有的框架也都是这样吧,对以往经验的高度总结,实现的代码的重构和复用。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值