EJB---->复合主键(Composite Primary Key)

来源:互联网 发布:洛阳平安数据科技待遇 编辑:程序博客网 时间:2024/05/16 01:50
当我们需要使用多个属性变量(表中的多列)联合起来作为主键,我们需要使用复合主键。复合主键要求我们编写一个复合主键类( 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;@Entitypublic 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;@Entitypublic 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;    }}