EJB>复合主键(Composite Primary Key) 小强斋

当我们需要使用多个属性变量(表中的多列)联合起来作为主键,我们需要使用复合主键。复合主键要求我们编写一个复合主键类( Composite Primary Key Class )。复合主键类需要符合以下一些要求:
·复合主键类必须是public 和具备一个没有参数的构造函数
·复合主键类的每个属性变量必须有getter/setter,如果没有,每个属性变量则必须是public 或者protected
·复合主键类必须实现java.io.serializable
·复合主键类必须实现equals()和hashcode()方法
·复合主键类中的主键属性变量的名字必须和对应的Entity 中主键属性变量的名字相同
·一旦主键值设定后,不要修改主键属性变量的值
本节以航线为例,介绍复合主键的开发过程,航线以出发地及到达地作为联合主键,航线与航班存在一对多的关联关系,下面是他们的数据库表

  flight

按照复合主键类的要求,我们编写一个复合主键类AirtLinePK.java,

package com.foshanshop.ejb3.bean;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable    复合主键使用一个可嵌入的类作为主键表示,@Embeddable 注释指明这是一个可嵌入的类
public class AirtLinePK implements Serializable {
private static final long serialVersionUID = -8430464367315480936L;
  private String leavecity;
    private String arrivecity;
    
    public AirtLinePK(){}
    
    public AirtLinePK(String leavecity, String arrivecity) {
        this.leavecity = leavecity;
        this.arrivecity = arrivecity;
    }

    @Column(nullable=false,length=3,name="LEAVECITY")
    public String getLeavecity() {
        return leavecity;
    }
    public void setLeavecity(String leavecity) {
        this.leavecity = leavecity;
    }
    
    @Column(nullable=false,length=3,name="ARRIVECITY")
    public String getArrivecity() {
        return arrivecity;
    }
    public void setArrivecity(String arrivecity) {
        this.arrivecity = arrivecity;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.leavecity!=null && this.arrivecity!=null ? (this.leavecity+ "-"+ this.arrivecity).hashCode() : 0);
        return hash;
    }
    
    @Override
    public boolean equals(Object object) {
        if (!(object instanceof AirtLinePK)) {
            return false;
        }
        AirtLinePK other = (AirtLinePK)object;
        if (this.leavecity != other.leavecity && (this.leavecity == null || !this.leavecity.equalsIgnoreCase(other.leavecity))) return false;
        if (this.arrivecity != other.arrivecity && (this.arrivecity == null || !this.arrivecity.equalsIgnoreCase(other.arrivecity))) return false;
        return true;
    }

    @Override
    public String toString() {
        return this.getClass().getName()+"[leavecity="+ leavecity + ",arrivecity="+ arrivecity+ "]";
    }
    
}
下面AirLine.java 用复合主键类AirtLinePK 作为其主键。@EmbeddedId 注释指明复合主键类作为主键。
AirLine.java
package com.foshanshop.ejb3.bean;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;

@Entity
public class AirLine implements Serializable {
private static final long serialVersionUID = -515855962558721968L;
private AirtLinePK id;
    private Boolean onoff;
    private Set<Flight> flights = new HashSet<Flight>();

    public AirLine(){}
    
    public AirLine(AirtLinePK id, Boolean onoff){
        this.id = id;   
        this.onoff = onoff;
    }

    @EmbeddedId
    public AirtLinePK getId() {
        return id;
    }
    public void setId(AirtLinePK id) {
        this.id = id;
    }

    public Boolean getOnoff() {
        return onoff;
    }

    public void setOnoff(Boolean onoff) {
        this.onoff = onoff;
    }

    @OneToMany(mappedBy="airline",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @OrderBy(value = "id ASC")
    public Set<Flight> getFlights() {
        return flights;
    }

    public void setFlights(Set<Flight> flights) {
        this.flights = flights;
    } 

    public void addFlight(Flight flight) {
        if (!this.flights.contains(flight)) {
             this.flights.add(flight);
             flight.setAirline(this);
        }
    }

    public void removeFlight(Flight flight) {
        if (this.flights.contains(flight)) {
            this.flights.remove(flight);
       }
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof AirLine)) {
            return false;
        }
        AirLine other = (AirLine)object;
        if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
        return true;
    }

    @Override
    public String toString() {
        return this.getClass().getName()+ "[id=" + id + "]";
    }
}
Flight.java
package com.foshanshop.ejb3.bean;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;

@Entity
public class Flight implements Serializable {
private static final long serialVersionUID = 5224268726211078831L;
private Integer id;  
    private String flightno;//航班号
    private String leavetime;//起飞时间
    private String arrivetime;//到达时间
    private AirLine airline;
    
    public Flight(){}

    public Flight(String flightno, String leavetime, String arrivetime) {
        this.flightno = flightno;
        this.leavetime = leavetime;
        this.arrivetime = arrivetime;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    
    @Column(nullable=false,length=10)
    public String getFlightno() {
        return flightno;
    }

    public void setFlightno(String flightno) {
        this.flightno = flightno;
    }
    
    @Column(length=10)
    public String getArrivetime() {
        return arrivetime;
    }

    public void setArrivetime(String arrivetime) {
        this.arrivetime = arrivetime;
    }
    
    @Column(length=10)
    public String getLeavetime() {
        return leavetime;
    }

    public void setLeavetime(String leavetime) {
        this.leavetime = leavetime;
    }

   @ManyToOne(cascade=CascadeType.REFRESH,optional=false) 
    @JoinColumns ({
        @JoinColumn(name="Leave_City", referencedColumnName = "LEAVECITY", nullable=false),
        @JoinColumn(name="Arrive_City", referencedColumnName = "ARRIVECITY", nullable=false)
        }) 

    public AirLine getAirline() {
        return airline;
    }

    public void setAirline(AirLine airline) {
        this.airline = airline;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.id != null ? this.id.hashCode() : super.hashCode());
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Flight)) {
            return false;
        }
        Flight other = (Flight)object;
        if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
        return true;
    }

    @Override
    public String toString() {
        return this.getClass().getName()+ "[id=" + id + "]";
    }
}
AirLineDAOBean.java
package com.foshanshop.ejb3.impl;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.foshanshop.ejb3.AirLineDAO;
import com.foshanshop.ejb3.bean.AirLine;
import com.foshanshop.ejb3.bean.AirtLinePK;
import com.foshanshop.ejb3.bean.Flight;

@Stateless
@Remote (AirLineDAO.class)
public class AirLineDAOBean implements AirLineDAO {
    @PersistenceContext protected EntityManager em;
    
    public void insertAirLine() {
     //如果你试图使用select count(a) from AirLine a 统计记录数,将会报错,这是Jboss4.2.2GA处理复合主键的Bug
        Query query = em.createQuery("select count(a.id.leavecity) from AirLine a where a.id.leavecity =?1 and a.id.arrivecity=?2");
        query.setParameter(1, "PEK"); 
        query.setParameter(2, "CAN");
        int result = Integer.parseInt(query.getSingleResult().toString());
        if (result==0){
            AirLine airLine = new AirLine(new AirtLinePK("PEK","CAN"), true);
            //PEK为首都机场三字码,CAN为广州白云机场三字码
            airLine.addFlight(new Flight("CA1321","08:45","11:50"));
            airLine.addFlight(new Flight("CZ3102","12:05","15:05"));
            airLine.addFlight(new Flight("HU7801","15:05","17:45"));
            em.persist(airLine);
        }
    }

    public AirLine getAirLineByID(String leavecity, String arrivecity) {
        AirLine airLine =  em.find(AirLine.class, new AirtLinePK(leavecity,arrivecity));       
        airLine.getFlights().size();
        //因为是延迟加载,通过执行size()这种方式获取航线下的所有航班
        return airLine;
    }
}


原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5637648.html