Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用JPA2.0注释m:n与助手类(2个外键和附加属性)的关系_Java_Jpa_Orm_Annotations_Jpa 2.0 - Fatal编程技术网

Java 用JPA2.0注释m:n与助手类(2个外键和附加属性)的关系

Java 用JPA2.0注释m:n与助手类(2个外键和附加属性)的关系,java,jpa,orm,annotations,jpa-2.0,Java,Jpa,Orm,Annotations,Jpa 2.0,我是JPA 2.0新手,在注释使用外键类的n:m关系时遇到问题,该外键类具有描述该关系的附加属性: 客户可以订阅多个杂志,每个订阅仅为一个客户和一个杂志创建,另外还节省了订阅的持续时间 这是我的注释类,我使用字段访问。我省略了一些样板代码,如构造函数、setter、getter(未注释)和方法toString、equals和hashCode @Entity public class Customer { @Id @GeneratedValue private Long i

我是JPA 2.0新手,在注释使用外键类的n:m关系时遇到问题,该外键类具有描述该关系的附加属性:

客户可以订阅多个杂志,每个
订阅
仅为一个
客户
和一个
杂志
创建,另外还节省了订阅的持续时间

这是我的注释类,我使用字段访问。我省略了一些样板代码,如构造函数、setter、getter(未注释)和方法
toString
equals
hashCode

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToMany
    private Set<Subscription> subscriptions;

    // ..
 }

@Entity
public class Magazine {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

    @ManyToMany
    private Set<Subscription> subscriptions;

    // ..
}

@Entity
public class Subscription {
    private Date start;
    private Date end;

    @EmbeddedId
    private SubscriptionId id;

    // ..
}

@Embeddable
public class SubscriptionId implements Serializable {
    @ManyToOne
    private Customer customer;
    @ManyToOne
    private Magazine magazine;

    // ..
}
提供程序将创建以下MySQL数据库:

mysql> show tables;
+-----------------------+
| Tables_in_kiosk       |
+-----------------------+
| customer              |
| customer_subscription |
| magazine              |
| magazine_subscription |
| subscription          |
+-----------------------+
只有三个表
客户
杂志
订阅
包含以下内容:

mysql> select * from customer;
+-------------+------+
| customer_id | name |
+-------------+------+
|           1 | cus1 |
|           2 | cus2 |
|           3 | cus3 |
+-------------+------+

mysql> select * from magazine;
+-------------+------+
| magazine_id | name |
+-------------+------+
|           1 | mag1 |
|           2 | mag2 |
+-------------+------+

mysql> select * from subscription;
+------+-------+-------------+-------------+
| end  | start | magazine_id | customer_id |
+------+-------+-------------+-------------+
| NULL | NULL  |           1 |           1 |
| NULL | NULL  |           1 |           2 |
| NULL | NULL  |           2 |           2 |
| NULL | NULL  |           2 |           3 |
+------+-------+-------------+-------------+
如果我知道订阅的密钥,我就可以阅读订阅。不过,我还没有试着为一位客户或杂志阅读整本书

private static void find(EntityManager em) {
    Magazine mag1 = em.find(Magazine.class, 1L);
    Magazine mag2 = em.find(Magazine.class, 2L);

    Customer cus1 = em.find(Customer.class, 1L);
    Customer cus2 = em.find(Customer.class, 2L);
    Customer cus3 = em.find(Customer.class, 3L);

    Subscription sub1 = em.find(Subscription.class, new SubscriptionId(cus1, mag1));
    Subscription sub2 = em.find(Subscription.class, new SubscriptionId(cus2, mag1));
    Subscription sub3 = em.find(Subscription.class, new SubscriptionId(cus2, mag2));
    Subscription sub4 = em.find(Subscription.class, new SubscriptionId(cus3, mag2));

    System.out.println(mag1);
    System.out.println(mag2);

    System.out.println(cus1);
    System.out.println(cus2);
    System.out.println(cus3);

    System.out.println(sub1);
    System.out.println(sub2);
    System.out.println(sub3);
    System.out.println(sub4);
}
印刷品:

Magazine [id=1, name=mag1, subscriptions=null]
Magazine [id=2, name=mag2, subscriptions=null]
Customer [id=1, name=cus1, subscriptions=null]
Customer [id=2, name=cus2, subscriptions=null]
Customer [id=3, name=cus3, subscriptions=null]
Subscription [start=null, end=null, id=SubscriptionId [customer=1, magazine=1]]
Subscription [start=null, end=null, id=SubscriptionId [customer=2, magazine=1]]
Subscription [start=null, end=null, id=SubscriptionId [customer=2, magazine=2]]
Subscription [start=null, end=null, id=SubscriptionId [customer=3, magazine=2]]
两个表
customer\u subscription
magazine\u subscription
保持为空。但在我看来,它们甚至都不是必需的——其他3张桌子看起来和我想要的一模一样。所以我的问题是:

如何在不创建多余表格的情况下,正确地对本例中使用的JPA 2.0中的m:n关系建模,同时保留为杂志或客户编写和读取所有订阅的能力?


如果有人对代码感兴趣,我已经上传到这里:;您需要一个名为“kiosk”的MySQL 5数据库,在本地主机上的3306端口运行,根密码为空。

您的模型实际上没有任何多对多关系

客户
订阅
是一对多。
杂志
订阅
是一对多

尝试将此作为您的实体模型:

@Entity
public class Customer {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany
    private Set<Subscription> subscriptions;

    // ..
 }

@Entity
public class Magazine {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany
    private Set<Subscription> subscriptions;

    // ..
}

@Entity
public class Subscription {

    private Date start;

    private Date end;

    @EmbeddedId
    private SubscriptionId id;

    // ..
}

@Embeddable
public class SubscriptionId implements Serializable {

    @ManyToOne
    private Customer customer;

    @ManyToOne
    private Magazine magazine;

    // ..
}
@实体
公共类客户{
@身份证
@生成值
私人长id;
私有字符串名称;
@独身癖
专用集订阅;
// ..
}
@实体
公共类杂志{
@身份证
@生成值
私人长id;
私有字符串名称;
@独身癖
专用集订阅;
// ..
}
@实体
公开课订阅{
私人约会开始;
私人约会结束;
@嵌入ID
私有订阅id;
// ..
}
@可嵌入
公共类SubscriptionId实现可序列化{
@许多酮
私人客户;
@许多酮
私人杂志;
// ..
}

Hibernate不会生成冗余链接表。

milkplusvellocetless的答案是解决方案的一部分,在
@OneToMany
注释中添加
mappedBy
属性可以解决问题:

@Entity
public class Magazine {
    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    @OneToMany(mappedBy = "id.magazine")
    private Set<Subscription> subscriptions;

    // ..

}

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    @OneToMany(mappedBy = "id.customer")
    private Set<Subscription> subscriptions;

    // ..
}

@Entity
public class Subscription {
    private Date start;
    private Date end;

    @EmbeddedId
    private SubscriptionId id;

    // ..
}

@Embeddable
public class SubscriptionId implements Serializable {
    @ManyToOne
    private Customer customer;
    @ManyToOne
    private Magazine magazine;

    // ..
}
@实体
公共类杂志{
@身份证
@生成值
私人长id;
@NotNull
私有字符串名称;
@OneToMany(mappedBy=“id.magazine”)
专用集订阅;
// ..
}
@实体
公共类客户{
@身份证
@生成值
私人长id;
@NotNull
私有字符串名称;
@OneToMany(mappedBy=“id.customer”)
专用集订阅;
// ..
}
@实体
公开课订阅{
私人约会开始;
私人约会结束;
@嵌入ID
私有订阅id;
// ..
}
@可嵌入
公共类SubscriptionId实现可序列化{
@许多酮
私人客户;
@许多酮
私人杂志;
// ..
}

仅创建3个表(根据需要),而不是5个表。

关于关系,您是对的,但是将
@manytomy
替换为
@OneToMany
并没有改变行为:JPA/Hibernate仍然创建两个不必要的空表
客户订阅
杂志订阅
。还是我遗漏了您在代码中更改的其他内容?您是否删除了整个数据库,然后让Hibernate重新生成所有内容?我不明白它为什么会这样。我仍然必须添加
mappedBy
属性。我添加了自己的答案,其中包括使用
@OneToMany
以及
mappedBy
属性。好。在陈述双向关系方面也值得注意。它有帮助,但没有解决问题——我现在提供了一个完整的解决方案,明天我只能标记为正确答案。我很感激你的帮助,也很乐意告诉你这一点,但我想避免让未来的读者感到困惑,因为我把答案标记为解决不了整个问题的解决方案。
@Entity
public class Magazine {
    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    @OneToMany(mappedBy = "id.magazine")
    private Set<Subscription> subscriptions;

    // ..

}

@Entity
public class Customer {
    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    @OneToMany(mappedBy = "id.customer")
    private Set<Subscription> subscriptions;

    // ..
}

@Entity
public class Subscription {
    private Date start;
    private Date end;

    @EmbeddedId
    private SubscriptionId id;

    // ..
}

@Embeddable
public class SubscriptionId implements Serializable {
    @ManyToOne
    private Customer customer;
    @ManyToOne
    private Magazine magazine;

    // ..
}