hibernate实现非主键映射外键双向多对一关系

1 many-to-one多对一端加property-ref关联主表的java对应类外键属性:

注:property-ref对应的是java类属性,不是表的字段

Order.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-9-17 15:48:32 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="cn.com.pojo.n21.both.notPK">
    <class name="Order" table="ORDERS_NOPK">

        <id name="orderId" type="java.lang.Integer">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>

        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" />
        </property>

        <!-- <many-to-one name="customer" class="cn.com.pojo.n21.Customer" fetch="join"> <column name="CUSTOMER" /> </many-to-one> -->

         <!-- 映射多对一的关联关系 :多端有个外键-->
         <!-- 使用 <many-to-one> 元素来映射多对一关联关系. name: 多这一端关联的一那一端的属性名 class: 一端属性对应的类名 column: 一端在多端对应的数据表中的外键名字 property-ref: 当一端是非主键的多对一端时候使用 -->
          <!-- 在多端设置外键 -->
         <many-to-one name="customer" class="Customer" property-ref="cyId">
            <column name="CUSTOMER_ID"/>  
         </many-to-one>

    </class>
</hibernate-mapping>

Order.java

package cn.com.pojo.n21.both.notPK;

public class Order {

    private Integer orderId;
    private String orderName;

    private Customer customer;

    public Order() {
        super();
        // TODO Auto-generated constructor stub
    }



    @Override
    public String toString() {
        return "Order [orderId=" + orderId + ", orderName=" + orderName
                +  "]";
    }


    public Integer getOrderId() {
        return orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public String getOrderName() {
        return orderName;
    }

    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

2 set一对多端也加property-ref关联主表的java对应类外键属性:

Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-9-17 15:48:32 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="cn.com.pojo.n21.both.notPK">
    <class name="Customer" table="CUSTOMERS_NOPK">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" />
        </property>

        <property name="cyId" type="java.lang.Integer">
            <column name="cy_id" not-null="true" unique="true"/>
        </property>

        <!-- 映射 1 对多 集合属性 -->
        <!-- set属性: -->
        <set name="orders" table="ORDERS" cascade="delete" inverse="true">
            <!-- key: 指定多端表中的外键列名字 -->
            <key column="CUSTOMER_ID" property-ref="cyId"></key>
            <!-- class指定映射java类 -->
            <one-to-many class="Order"/>
        </set>
    </class>
</hibernate-mapping>

Customer.java

package cn.com.pojo.n21.both.notPK;

import java.util.HashSet;
import java.util.Set;

public class Customer {

    private Integer id;
    private Integer cyId;
    private String customerName;

    /* * 1 声明集合类型时候,需要用接口类型,因为hibernate在存取集合类型时, * 返回的是hibernate内置的集合类型,而不是javaSE一个标准的集合实现。 * 2 把集合set进行初始化,可以防止发生空指针异常; */
    private Set<Order> orders = new HashSet<>();
    public Customer() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getCustomerName() {
        return customerName;
    }
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
    public Set<Order> getOrders() {
        return orders;
    }
    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }
    public Integer getCyId() {
        return cyId;
    }
    public void setCyId(Integer cyId) {
        this.cyId = cyId;
    }
    @Override
    public String toString() {
        return "Customer [id=" + id + ", cyId=" + cyId + ", customerName="
                + customerName + ", orders=" + orders + "]";
    }
}

3 测试:

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 配置连接数据库的基本信息 -->
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql:///hibernate</property>

        <!-- 配置hibernate基本信息 -->
        <!-- hibernate所用数据库方言 数据库类型 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 执行操作时候是否在控制台打印sql -->
        <property name="show_sql">true</property>
        <!-- 是否对sql进行格式化 -->
        <property name="format_sql">true</property>
        <!-- 指定自动生成表的策略 update create-->
        <property name="hbm2ddl.auto">create</property>
        <!-- 指定关联的.hbm.xml -->
        <mapping resource="cn/com/pojo/n21/both/notPK/Customer.hbm.xml"/>
        <mapping resource="cn/com/pojo/n21/both/notPK/Order.hbm.xml"/> 
    </session-factory>
</hibernate-configuration>

Many2OneTest.java

package cn.com.pojo.n21.both.notPK;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Many2OneTest {

    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void init(){
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = 
                new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                            .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);

        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void destroy(){
        transaction.commit();
        session.close();
        sessionFactory.close();
    }

    @Test
    public void tesSave(){
        Customer c = new Customer();
        c.setCyId(102);
        c.setCustomerName("BB");

        Order o1 = new Order();
        o1.setOrderName("ORDER-O1");

        Order o2 = new Order();
        o2.setOrderName("ORDER-O2");

        //设定双向关联关系
        o1.setCustomer(c);
        o2.setCustomer(c);

        c.getOrders().add(o1);
        c.getOrders().add(o2);


        //执行save
        // 先插入1端,再插入多端,3条insert语句,2条update
        // 因为1端和n端都维护关联关系,所以多出2个update
        // 可以在1端的set节点指定inverse=true,使1端放弃维护关联关系,此时不会有update
        // 建议设定set的inverse=true,建议先插入1端再插入多端,不会出现update语句。
        session.save(o1);
        session.save(o2);
        session.save(c);
    }
}

测试结果:

这里写图片描述

这里写图片描述

这里写图片描述

相关文章

相关标签/搜索
每日一句
    每一个你不满意的现在,都有一个你没有努力的曾经。