【问题标题】:Hibernate many-to-many with map collection使用地图集合休眠多对多
【发布时间】:2011-01-07 01:57:48
【问题描述】:

我有两个表“站”和“路线”。路线可以包含许多站点,每个站点都可以是不同路线的一部分。合乎逻辑的解决方案是创建一个包含“station_id”和“route_id”字段的表,互联网上有很多示例如何使用 hibernate 组织所有这些东西。但是我需要将每个站点的订单号存储在路线中,因此第三个表填充了一个额外的字段'orderNumber',因此我们得到以下结构:

路线站

  • route_id
  • station_id
  • 订单号

我创建了下一个 bean:

public class Station extends Identifier{

    private String title;
}

public class Route extends Identifier{
    private String name;
    private Map<Integer, Station> stations = new HashMap<Integer, Station>();
}

所以我使用 HashMap 集合来存储 orderNumber 变量。 请帮助我使用休眠映射这种类型的关系或提出其他解决方案。 谢谢。

【问题讨论】:

    标签: java hibernate nhibernate-mapping many-to-many


    【解决方案1】:

    由于您必须在 RouteStation 表中存储额外信息,因此将其提升为完整类可能会更好。你最终会得到这样的结果:

     public class Station extends Identifier{
        private String title;
        private List<RouteStation> routes;
     }
    
     public class Route extends Identifier{
        private String name;
        private List<RouteStation> stations;
     }
    
     Public class RouteStation{
         private Station station;
         private Route route;
         private Integer orderNumber;
     }
    

    然后您可以进行映射,以便 RouteStation 类拥有 Route 和 Station 之间的关系。您现在必须创建两个单独的一对多双向映射。

    【讨论】:

    • 是的,这是显而易见的解决方案,但是数据库中的关系模型反映了这里的对象,而我认为对象必须使用对象模型。必须是一种组织多对多的方式,就像我上面回答的那样,但我对此感到困惑。
    【解决方案2】:

    嗯,

    我需要存储路线中每个站点的订单号

    为什么不使用列表来代替。你只需要创建一个链接表

    @Entity
    public class Route {
    
        private Integer id;
    
        private List<RouteAndStation> stationList = new ArrayList<RouteAndStation>();
    
        @Id
        public Integer getId() {
            return this.id;
        }
    
        @OneToMany(mappedBy="route")
        @Cascade(SAVE_UPDATE)
        public List<RouteAndStation> getStationList() {
            return this.stationList;
        }
    
        @Transient
        public List<Station> getStationByOrderNumber() {
            Collections.sort(this.stationList, new Comparator<RouteAndStation>() {
                public int compare(RouteAndStation o1, RouteAndStation o2) {
                    return o1.getOrderNumber().compareTo(o2.getOrderNumber());
                }
            });
    
            List<Station> sList = new ArrayList();
            for(RouteAndStation routeAndStation: this.stationList)
                sList.add(routeAndStation.getStation());
    
            return sList;
        }
    
        public void addStation(Station station) {
            RouteAndStation routeAndStation = new RouteAndStation();
    
            routeAndStation.addStation(this, station, getStationList().size());
    
            getStationList().add(routeAndStation);
        }
    
    }
    

    和车站

    @Entity
    public class Station {
    
        private Integer id;
    
        private List<RouteAndStation> routeList = new ArrayList<RouteAndStation>();
    
        @Id
        public Integer getId() {
           return this.id;
        }
    
        @OneToMany(mappedBy="station")
        // DO YOU NEDD CASCADE ???
        @Cascade(SAVE_UPDATE)
        public List<RouteAndStation> getRouteList() {
            return this.routeList;
        }
    
    
    }
    

    RouteAndStation 实现如下

    @Entity
    public class RouteAndStation {
    
        private Route route;
        private Station station;
    
        private Integer stationNumber;
    
        private RouteAndStationId routeAndStationId;
    
        @EmbeddedId
        public RouteAndStationId getRouteAndStationId() {
            return this.routeAndStationId;
        }
    
        public void addStation(Route route, Station station, Integer stationNumber) {
            this.route = route;
            this.station = station;
    
            this.stationNumber = stationNumber;
    
            setRouteAndStationId(new RouteAndStationId(route.getId(), station.getId));
        }
    
        @ManyToOne(fetch=LAZY)
        @JoinColumn(name="ROUTE_ID", insertable=false, updateable=false)
        public Route getRoute() {
            return this.route;
        }
    
        @ManyToOne(fetch=LAZY)
        @JoinColumn(name="STATION_ID", insertable=false, updateable=false)
        public Station getStation() {
            return this.station;
        }
    
        @Embeddable
        public static class RouteAndStationId implements Serializable {
    
            private Integer routeId;
            private Integer stationId;
    
            // required no-arg constructor
            public RouteAndStationId() {}
    
            public RouteAndStationId(Integer routeId, Integer stationId) {
                this.routeId = routeId;
                this.stationId = stationId;
            }
    
            @Column(name="ROUTE_ID")
            public Integer getRouteId {
                return this.routeId;
            }
    
            @Column(name="STATION_ID")
            public Integer getStationId {
                return this.stationId;
            }
    
            public boolean equals(Object o) {
                if(o == null)
                    return false;
    
                if(!(o instanceof RouteAndStationId))
                    return false;
    
                RouteAndStationId other = (RouteAndStationId) o;
                if(!(getRouteId().equals(other.getRouteId())))
                    return false;
    
                if(!(getStationId().equals(other.getStationId())))
                    return false;
    
                return true;
            }
    
        }
    
    }
    

    希望对你有用

    问候,

    【讨论】:

      【解决方案3】:

      非常感谢。但我认为不应该有“RouteAndStation”实体。我试图将我的“路线”类映射到数据库中的两个表上,如下所示:

      <class name="Route" table="Route">
      
          <id name="id" column="routeId" type="long" unsaved-value="-1">
                  <generator class="native"/>
          </id>
      
          <property name="name" column="name" />
      
          <map name="stations" table="RouteStations" cascade="all">
                  <key column="routeId" />
                  <map-key-many-to-many column="stationId" class="Station"/>
                  <element column="orderNumber" type="int"/>
              </map>
      
      </class>
      

      但是当我保存 Route 对象时,休眠只执行一个查询:

      insert into Route (name) values (?)
      

      【讨论】:

      • @j3raks 只是一个建议:你想使用地图作为避免加入班级的一种方式,对吗???但是如果你需要在链接表上添加一个新属性会发生什么???您需要更改所有模型。想想看。您的应用不需要知道您加入的班级。如果您看到,封装用于隐藏您加入的类。谢谢。
      • 是的,我看到了封装。我会使用你的解决方案。非常感谢。
      猜你喜欢
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 2012-04-07
      • 1970-01-01
      • 2021-08-28
      相关资源
      最近更新 更多