注解方式实现级联

时间:2022-06-17
本文章向大家介绍注解方式实现级联,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

级联

级联分为一对多,多对一单向,多对多双向关联。一般情况下,我们只会用到前两种情况,多对多用的较少。我这里使用省市区三级联查来实现级联的操作。简单来说,一对多就是一个省下面有多个市,一个市下面有多个县。多对一是刚好反过来的。

首先是使用配置文件的情况下,关联类,生成的hbm.xml文件中显示如下:

<hibernate-mapping>

    <class name="com.qy.domain.Province" table="province" schema="java1807">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="code" column="code"/>
        <property name="name" column="name"/>
        <!--
        name:当前类的属性名
        column:从表中的外键名
        foreign-key:主表中的被参照字段
        property-ref:主表中被参照字段的属性名
        class:从表的类
         lazy:true 使用懒加载机制  默认
        lazy:false 放弃懒加载
        inverse:true 放弃主控权
        inverse:false 默认
        -->
        <set name="cities" cascade="all" lazy="true" inverse="true">
            <key column="provincecode" foreign-key="code" property-ref="code"></key>
            <one-to-many class="com.qy.domain.City"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

hibernate.hbm.xml配置如下:

 <mapping class="com.qy.domain.Province"></mapping>
        <mapping class="com.qy.domain.City"></mapping>
        <mapping class="com.qy.domain.Area"></mapping>

使用注解:

就是把mapping配置文件跟换掉。注解方式不需要在xxx.hbm.xml把实体类与表进行映射。而采用在实体类中进行注解。

注意:

(1):如果实体类属性名与表字段名不一致的时候,要么都注解在属性前,要么都注解在get方法前。不能部分注解在属性前,部分注解在方法前。

(2):如果实体类属性名与表字段名一致的时候,可以部分注解在属性前,部分注解在方法前。

(3):如果在实体类中某些属性不注解:(属性和get都不写注解),默认为表字段名与实体类属性名一致。

(4):如果实体类的某个成员属性不需要对这个成员属性进行映射))

(5):表名称可以在实体类前进行注解。

(6):所有这些注解在:javax.persistence包下。而不是在hibernate包中

  <mapping resource="Area.hbm.xml"/>
        <mapping resource="City.hbm.xml"/>
        <mapping resource="Province.hbm.xml"/>

实体类配置如下:

@Entity
@Table(name = "province",schema = "java1807")
public class Province implements Serializable {
    private int id;
    private String code;
    private String name;
    private Set<City> cities=new HashSet<>();
    @Id
    @Column(name ="id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Column(name="code")
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @OneToMany(cascade= CascadeType.ALL,mappedBy ="province")
    public Set<City> getCities() {
        return cities;
    }
    public void setCities(Set<City> cities) {
        this.cities = cities;
    }
    public Province() {
    }

    public Province(int id, String code, String name) {
        this.id = id;
        this.code = code;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Province{" +
                "id=" + id +
                ", code='" + code + ''' +
                ", name='" + name + ''' +
                '}';
    }
}

多对一关联

city.hbm.xml文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.qy.domain.City" table="city" schema="java1807">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="code" column="code"/>
        <property name="name" column="name"/>

        <!--
        多对一关联
        name:city中属性名province
        colum:city表中对应的列名
        class:属性名province对应的对象类
        如果通过主键关联不需要配置property-ref
        如果不通过主键关联需要配置property-ref:指向Province类中参照的属性名
        cascade:save-update,强制级联更新
        -->
        <many-to-one name="province" class="com.qy.domain.Province" property-ref="code" cascade="all">
            <column name="provincecode"></column>
        </many-to-one>

    </class>
</hibernate-mapping>

使用注解对city进行改进,实体类配置如下:

@Entity
@Table(name="city",schema = "java1807")
public class City {
    private int id;
    private String code;
    private String name;
    /*private String provincecode;*/
    private Province province;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return id;
    }

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

    @Column(name="code")
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
   /* public String getProvincecode() {
        return provincecode;
    }
    public void setProvincecode(String provincecode) {
        this.provincecode = provincecode;
    }*/
   @ManyToOne(targetEntity = Province.class)
   @JoinColumn(name="provincecode",referencedColumnName = "code")
    public Province getProvince() {
        return province;
    }

    public void setProvince(Province province) {
        this.province = province;
    }

    @Override
    public String toString() {
        return "City{" +
                "id=" + id +
                ", code='" + code + ''' +
                ", name='" + name + ''' +
                '}';
    }
}

这是我写的测试类,对级联进行增删查改功能。

public class Test2 {
    @Test
    public void testQuary(){
      Session session = HibernateUtill.getCurrentSession();
      List<Province> list = session.createQuery("from Province").list();
      HibernateUtill.sessionClose(session);
    }
    
    @Test
    public void testSave(){
        Session session = HibernateUtill.getCurrentSession();
        session.beginTransaction();

        Province p = new Province();
        p.setName("腾飞省");
        p.setCode("830000");
        Set<City> cities = new HashSet<City>();
        City c1 = new City();
        c1.setName("腾飞市1");
        c1.setCode("830100");
        City c2 = new City();
        c2.setName("腾飞市2");
        c2.setCode("830200");
        cities.add(c1);
        cities.add(c2);
        p.setCities(cities);
        session.save(p);
        session.getTransaction().commit();
        HibernateUtill.sessionClose(session);
    }

    @Test
    public void testUpdate(){
        Session session = HibernateUtill.getCurrentSession();
        session.beginTransaction();

        Province p = session.get(Province.class,39);
        p.setName("腾飞市");
        Set set = p.getCities();
        Iterator it = set.iterator();
        int i =1;
      while(it.hasNext()){
          City c = (City) it.next();
            c.setName("腾飞"+i++);
        }
        session.update(p);
        session.getTransaction().commit();
        HibernateUtill.sessionClose(session);
    }

    @Test
    public void testDelete(){
        Session session = HibernateUtill.getCurrentSession();
        session.beginTransaction();
        Province p = session.get(Province.class,39);
        session.delete(p);
        session.getTransaction().commit();
        HibernateUtill.sessionClose(session);
    }

总结

注解相对于配置文件更加简单,但还是没有配置文件好理解,建议新手还是先回使用配置文件。