2015-02-09 73 views
1

我想使用Hibernate注释将映射列表映射到类中。如何使用注释映射Hibernate中的地图列表?

我想我最后类是这个样子:

@Entity 
@Table(name = "PERSON") 
public class Person { 
    @Id 
    @GeneratedValue 
    private long id; 

    @OneToMany(mappedBy = "person") 
    private List<Map<String, Trip>> trips; 
} 

TRIP表具有与行程走遍通过国家每趟行程数和多行。

@Entity 
@Table(name = "TRIP") 
public class Trip { 
    @Id 
    @GeneratedValue 
    private long id; 

    @Column(name = "PERSON_ID") 
    private Person person; 

    @Column(name = "TRIP_NO") 
    private int trip_no; 

    @Column(name = "STATE") 
    private String state; 

    ... 
} 

所以行程表中有这些列:

Name   Type 
ID   NUMBER(9) 
PERSON_ID NUMBER(9) 
TRIP_NO  LONG 
STATE  VARCHAR2(16) 
. 
. 
. 

ID PERSON_ID TRIP_NO STATE ... 
1 1   1  MN ... 
2 1   1  WI ... 
3 1   2  ND ... 
4 1   2  MT ... 
5 2   1  IA ... 

所以在地图的列表中,TRIP_NO是List的索引和状态的关键地图。第一人参加了两次旅行,第一次是明尼苏达州和威斯康星州,第二次去北达科他州和蒙大拿州。 2号人1次前往爱荷华州。

我无法通过浏览找到如何指定此配置。

第二个问题:可以在没有JPA 2的情况下完成吗?

+0

“@ OneToMany”注释和朋友描述数据库实体之间的关系。我无法确定Map 是什么实体。 – mpkorstanje 2015-02-09 23:28:36

+0

Map 映射按状态键入的一组行程数据。因此,该地图将包含所有具有相同TRIP_NO的行程和由该行程所处状态键入的人员。因此,'person1.getTrips()。get(1)是{{“MN”,tripdata1},{“WI “,tripdata2}}'。 'person1.getTrips()。get(2)是{{“ND”,tripdata1},{“MT”,tripdata2}}'。 'person2.getTrips()。get(1)是{{“IA”,tripdata1}}'。 – 2015-02-09 23:42:39

+0

啊我明白了。那么你的TRIP表中有太多的信息。它包含旅行和旅行目的地实体。看到我发布的答案。 – mpkorstanje 2015-02-10 00:03:59

回答

1

这里是我的方法:

// composite primary key 
public class TripId implements Serializable { 
    private int id; 
    private long trip_no; 

    public TripId(int id, long trip_no) { 
     this.id = id; 
     this.trip_no = trip_no; 
    } 

    // getters, setters, hashCode, equals 
} 

编辑:我不得不更新从下面的评论Welshbard的问题后,实体模型。的变化是:

  • Person实体:Map<String, Trip> trips;取代List<Trip> trips;
  • Trip实体:String state;字段添加作为替代trips键从Person实体
  • 构造/ setter方法/代码段用于填充数据/输出模式是相应更新
@Entity 
public class Person { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int id; 

    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL) 
    private List<Trip> trips; 

    public Person() { 
     this.trips = new List<>(); 
    } 

    public void setTrips(List<Trip> trips) { 
     this.trips = trips; 
    } 

    ... 
} 
@Entity 
@IdClass(TripId.class) 
public class Trip { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int id; 

    @Id 
    private long trip_no; 

    private String state; 

    @ManyToOne 
    private Person person; 

    public Trip() { 

    } 

    public Trip(String state, long trip_no, Person person) { 
     this.state = state; 
     this.trip_no = trip_no; 
     this.person = person; 
    } 

    ... 
} 

现在,我们可以利用上面的ORM的,并填充一些数据:

Person person1 = new Person(); 
Person person2 = new Person(); 

Trip mn1Trip1 = new Trip("MN", 1, person1); 
Trip wi1Trip1 = new Trip("WI", 1, person1); 
Trip nd2Trip1 = new Trip("ND", 2, person1); 
Trip mt2Trip1 = new Trip("MT", 2, person1); 
Trip ia1Trip2 = new Trip("IA", 1, person2); 
// more than one trip by a person goes to the same state 
Trip mn2Trip1 = new Trip("MN", 2, person1); 
Trip ia2Trip2 = new Trip("IA", 2, person2); 
Trip mn1Trip2 = new Trip("MN", 1, person2); 

person1.setTrips(Arrays.asList(mn1Trip1, wi1Trip1, nd2Trip1, mt2Trip1, mn2Trip1)); 
person2.setTrips(Arrays.asList(ia1Trip2, ia2Trip2, mn1Trip2)); 

em.getTransaction().begin(); 
em.persist(person1); 
em.persist(person2); 
em.getTransaction().commit(); 

最后,我们可以查询数据库,看的模式以及如何被填充的信息:

Person table 
============ 
id 
-- 
1 
7 

Trip table 
=========== 
id trip_no person_id state 
-- ------- --------- ----- 
    9  2 IA   7 
    4  2 ND   1 
    8  1 IA   7 
    6  2 MN   1 
    2  1 MN   1 
10  1 MN   7 
    3  1 WI   1 
    5  2 MT   1 

注意:ids是不同的,但架构已正确创建并且数据按预期填充。

至于从下面的评论的问题:

// Person class have only trips associated with that person 
String jpql1 = "SELECT p.trips FROM Person p WHERE p.id = 1"; 
List<Trip> trips = em.createQuery(jpql1, Trip.class) 
        .getResultList(); 

// the code can look at the Trips to find out the trip_no 
String jpql2 = "SELECT t.trip_no FROM Trip t JOIN Person p " + 
       "WHERE p.id = :id AND t.state = :state"; 
List<Long> trip_nos = em.createQuery(jpql2, Long.class) 
         .setParameter("id", 1) 
         .setParameter("state", "MN") 
         .getResultList(); 

关于第二个问题:

可以毫不JPA 2做些什么呢?

您可以尝试使用普通的旧JDBC并使用java.sql.Statement来插入SQL语句。

+0

使用TripId匹配数据库模式,但不匹配OP想要的集合映射。 OP想要映射不可能的'List >'。 – mpkorstanje 2015-02-10 21:44:32

+0

Person类中的地图是否只有与该人关联的旅行?代码可以查看Trips以查明trip_no?如果一个人不止一次旅行到同一州,会怎么样? – 2015-02-11 16:10:21

+0

@mpkorstanje:这是不可能的。我完全同意。这就是为什么我们试图提供一个至少符合威尔斯巴德模式的实体模型,对吗? – wypieprz 2015-02-11 21:18:15

0

我不知道,因为没有测试之前同样的事情还没有确切经历过,但我想用Map<K,V>List A S为关联领域将是一个有点复杂,您可以在一个相对Many-to-Oneperson在人实体Trip实体然后One-to-ManyTrips

@Entity 
@Table(name = "TRIP") 
public class Trip {  
    /* 
    code 
    */ 
    @ManyToOne(cascade=CascadeType.ALL) 
    private Person person; 

    /* 
    code 
    */ 
} 

Person实体不使用List<Map<String, Trip>>,而不是用它@MapKey标注为Map<String, Trip>

@Entity 
@Table(name = "PERSON") 
public class Person { 
    @Id 
    @GeneratedValue 
    private long id; 

    @OneToMany(mappedBy = "person") 
    @MapKey(name = "state") 
    private Map<String, Trip> trips; 
} 

但是您需要查看更多,我希望这会有所帮助。

+0

TRIP_NO是不是唯一的,它是如何处理的?或者是否必须通过@PostLoad来处理地图以获取旅行地图列表?让我在问题中加一点来说明这一点。 – 2015-02-09 22:47:20

+0

如果一个人的一次以上的旅程进入相同的状态会怎样? – 2015-02-11 16:11:59

+0

哦,我真的很抱歉在回复您的意见时出现延迟,我有几天没有在Stackoverflow上发表过。你的情况有点复杂,需要更多的评论,我对目前没有专注和时间表示歉意(mybe几天后),我希望你很快就会得到解决,你也可以编辑或完成我的答案if很有用,祝你好运 – jfun 2015-02-11 16:21:08

0

除非你改变你的数据库模式,你想要的是不可能的。注意Hibernate文档如何将集合类型省略为集合的有效内容。

当然,Hibernate也允许保存集合。这些持久集合可以包含几乎任何其他Hibernate类型,其中包括:基本类型,自定义类型,组件和对其他实体的引用。 From Hibernate Collection Mapping

,因为你的数据库设计是靠不住的你不能用休眠做到这一点。基本上你的TRIP表有太多的信息,因为它存储旅行和目的地。

理想情况下,您有旅行和目的地。

行程由一个id,一个person_id和一个trip_no组成,列表中的排序通过@OrderBy

目的地包含一个ID,一个trip_id,供@MapKey使用的state_id和目的地的其他信息。

Java代码会是这样的。没有检查任何错误。只是为了给你这个想法。

@Entity 
@Table(name = "PERSON") 
public class Person { 
    @Id 
    @GeneratedValue 
    private long id; 

    @OneToMany(mappedBy = "person") 
    @OrderBy(clause=trip_no) 
    private List<Trip> trips; 
} 

@Entity 
@Table(name = "TRIP") 
public class Trip { 
    @Id 
    @GeneratedValue 
    private long id; 

    @Column(name = "PERSON_ID") 
    private Person person; 

    @Column(name = "TRIP_NO") 
    private int trip_no; 

    @OneToMany(mappedBy = "trip") 
    @MapKey(name = "state") 
    private Map<String,Destination> destinations 
} 

@Entity 
@Table(name = "DESTINATION") 
public class Destination { 

    private Trip trip; 

    @Column(name = "STATE") 
    private String state; 

    ... 
} 
相关问题