使用JPA和Hibernate进行JoiningTables时出现了多重映射失败的问题。

huangapple go评论89阅读模式
英文:

JoiningTables using jpa and hibernate problem is mulitmapping failed

问题

我在两个月前刚开始学习Java EE,以下是我在一些部分遇到困难的代码:

@Entity
@Table(name="booking")
public class Booking implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int reservationId;
    private String stateroomType;
    private double totalAmount;
    private int totalGuests;
    private int shipId;
    private int passId;
	 
    //Joining Tables
    @OneToOne
    @JoinColumn(name="passId")
    private Passenger passenger;

    @ManyToOne
    @JoinColumn(name="shipId")
    private Cruise cruise;
}

@Entity
@Table(name = "shipcruise")
public class Cruise implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int cruiseId;
    private String cruiseName;
    private LocalDate startDate;
    private LocalDate endDate;
    private Timestamp destination;
}

@Entity
@Table(name = "passengers")
public class Passenger implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int passengerId;
    private String userName;
    private String firstname;
    private String lastname;
    private String address;
    private String city;
    private String country;
    private String postalCode;
    private String password;
}

当我运行项目时,我收到以下错误消息:

异常[EclipseLink-48](Eclipse持久性服务-2.5.2.v20140319-9ad6abd):org.eclipse.persistence.exceptions.DescriptorException
异常描述:字段[booking.SHIPID]存在多个可写映射。只能定义一个为可写,其他所有字段必须指定为只读。
映射:org.eclipse.persistence.mappings.OneToOneMapping[cruise]
描述符:RelationalDescriptor(com.springmvc.jpa.booking.Booking -> [DatabaseTable(booking)])
异常[EclipseLink-48](Eclipse持久性服务-2.5.2.v20140319-9ad6abd):org.eclipse.persistence.exceptions.DescriptorException
异常描述:字段[booking.PASSID]存在多个可写映射。只能定义一个为可写,其他所有字段必须指定为只读。
映射:org.eclipse.persistence.mappings.OneToOneMapping[passenger]
描述符:RelationalDescriptor(com.springmvc.jpa.booking.Booking -> [DatabaseTable(booking)])

我理解在映射中存在问题,我已经进行了一些研究,但仍然无法理解如何解决问题或如何在实体类之间建立关系。有人可以帮助我找出问题并解决吗?

数据库表:

CREATE TABLE `booking` (
 `reservationId` int NOT NULL,
 `stateroomType` varchar(30) NOT NULL,
 `totalGuests` int NOT NULL,
 `totalAmount` decimal(10,2) NOT NULL,
 `passId` int DEFAULT NULL,
 `shipId` int DEFAULT NULL,
  PRIMARY KEY (`reservationId`),
  KEY `passId` (`passId`),
  KEY `shipId` (`shipId`),
  CONSTRAINT `booking_ibfk_1` FOREIGN KEY (`passId`) REFERENCES 
  `passengers` (`passengerId`),
  CONSTRAINT `booking_ibfk_2` FOREIGN KEY (`shipId`) REFERENCES 
  `shipcruise` (`cruiseId`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `passengers` (
 `passengerId` int NOT NULL AUTO_INCREMENT,
 `userName` varchar(50) DEFAULT NULL,
 `password` varchar(25) DEFAULT NULL,
 `firstname` varchar(30) DEFAULT NULL,
 `lastname` varchar(30) DEFAULT NULL,
 `address` varchar(255) DEFAULT NULL,
`city` varchar(25) DEFAULT NULL,
`postalCode` varchar(10) DEFAULT NULL,
 `country` varchar(20) DEFAULT NULL,
 PRIMARY KEY (`passengerId`)
 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 
   COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `shipcruise` (
 `cruiseId` int NOT NULL AUTO_INCREMENT,
 `CruiseName` varchar(50) DEFAULT NULL,
 `shipName` varchar(50) DEFAULT NULL,
`startDate` date NOT NULL,
`endDate` date NOT NULL,
 `destination` timestamp NOT NULL,
 PRIMARY KEY (`cruiseId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
英文:

I just started learning java ee two months ago and I am struggling in some parts as showing below.
I have three entity classes for a booking system and struggling in running the project after I had done some logic:

     @Entity
@Table(name="booking")
public class Booking implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int reservationId;
private String stateroomType;
private double totalAmount;
private int totalGuests;	
private int shipId;
private int passId;
//Joining Tables
@OneToOne
@JoinColumn(name="passId")
private Passenger passenger;
@ManyToOne
@JoinColumn(name="shipId")
private Cruise cruise;
@Entity
@Table(name = "shipcruise")
public class Cruise implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int cruiseId;
private String cruiseName;
private LocalDate startDate;
private LocalDate endDate;
private Timestamp destination;
@Entity
@Table(name = "passengers")
public class Passenger implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int passengerId;
private String userName;
private String firstname;
private String lastname;
private String address;
private String city;
private String country;
private String postalCode;
private String password;

When I run my project I get this error message:

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [booking.SHIPID]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[cruise]
Descriptor: RelationalDescriptor(com.springmvc.jpa.booking.Booking --> [DatabaseTable(booking)])
Exception [EclipseLink-48] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [booking.PASSID]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[passenger]
Descriptor: RelationalDescriptor(com.springmvc.jpa.booking.Booking --> [DatabaseTable(booking)])

.................................................................................................

I understand that there is a problem in the mapping and I have made some research about it but still can not get the idea of how to solve it or how to make the relationship between the entity classes. Can anyone help me figure out the problem and solve it.

Database tables:

      CREATE TABLE `booking` (
`reservationId` int NOT NULL,
`stateroomType` varchar(30) NOT NULL,
`totalGuests` int NOT NULL,
`totalAmount` decimal(10,2) NOT NULL,
`passId` int DEFAULT NULL,
`shipId` int DEFAULT NULL,
PRIMARY KEY (`reservationId`),
KEY `passId` (`passId`),
KEY `shipId` (`shipId`),
CONSTRAINT `booking_ibfk_1` FOREIGN KEY (`passId`) REFERENCES 
`passengers` (`passengerId`),
CONSTRAINT `booking_ibfk_2` FOREIGN KEY (`shipId`) REFERENCES 
`shipcruise` (`cruiseId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `passengers` (
`passengerId` int NOT NULL AUTO_INCREMENT,
`userName` varchar(50) DEFAULT NULL,
`password` varchar(25) DEFAULT NULL,
`firstname` varchar(30) DEFAULT NULL,
`lastname` varchar(30) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`city` varchar(25) DEFAULT NULL,
`postalCode` varchar(10) DEFAULT NULL,
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`passengerId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `shipcruise` (
`cruiseId` int NOT NULL AUTO_INCREMENT,
`CruiseName` varchar(50) DEFAULT NULL,
`shipName` varchar(50) DEFAULT NULL,
`startDate` date NOT NULL,
`endDate` date NOT NULL,
`destination` timestamp NOT NULL,
PRIMARY KEY (`cruiseId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

答案1

得分: 0

Booking实体。

@Entity
@Table(name="booking")
public class Booking implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer reservationId;
    private String stateroomType;
    private double totalAmount;
    private int totalGuests;

    //Joining Tables
    @ManyToOne
    @JoinColumn(name="passId")
    private Passenger passenger;

    @ManyToOne
    @JoinColumn(name="shipId")
    private Cruise cruise;
}

Cruise实体。

@Entity
@Table(name = "shipcruise")
public class Cruise implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer cruiseId;
    private String cruiseName;
    private LocalDate startDate;
    private LocalDate endDate;
    private Timestamp destination;
}

Passengers实体。

@Entity
@Table(name = "passengers")
public class Passenger implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer passengerId;
    private String userName;
    private String firstname;
}

在你的代码中,你有:

private int shipId;
private int passId;

以下是你的代码中的部分:

//Joining Tables
@OneToOne
@JoinColumn(name="passId")
private Passenger passenger;

@ManyToOne
@JoinColumn(name="shipId")
private Cruise cruise;

当你不使用@Column或@JoinColumn时,EclipseLink将使用字段名称,因此,在这种情况下,你将有两个指向同一列的Java属性。

@JoinColumn为你执行了脏工作(引用另一个引用SQL表的实体),这就是为什么我们使用JPA的原因。

我将表示主键的字段从int更改为Integer类。
你可以在这里找到原因:https://stackoverflow.com/questions/2565352/whats-difference-between-primitive-and-wrapper-class-in-jpa-hibernate-column

英文:

Booking entity.

 @Entity
@Table(name="booking")
public class Booking implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer reservationId;
private String stateroomType;
private double totalAmount;
private int totalGuests;   
//Joining Tables
@ManyToOne
@JoinColumn(name="passId")
private Passenger passenger;
@ManyToOne
@JoinColumn(name="shipId")
private Cruise cruise;

Cruise entity.

@Entity
@Table(name = "shipcruise")
public class Cruise implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cruiseId;
private String cruiseName;
private LocalDate startDate;
private LocalDate endDate;
private Timestamp destination;

Passengers entity.

@Entity
@Table(name = "passengers")
public class Passenger implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer passengerId;
private String userName;
private String firstname;

In you code, you have:

 private int shipId;
private int passId;

and below, you have:

  //Joining Tables
@OneToOne
@JoinColumn(name="passId")
private Passenger passenger;
@ManyToOne
@JoinColumn(name="shipId")
private Cruise cruise;

When, you do not use, @Column or @JoinColumn, the eclipse-link will use the field name, so, in this case, you will have 2 java properties that point to same column.

@JoinColumn does the dirty work for you(reference the other entity that references the SQL table), that is why we use JPA.

I changed the fields that represent primary key from int to Integer class.
You can find why here: https://stackoverflow.com/questions/2565352/whats-difference-between-primitive-and-wrapper-class-in-jpa-hibernate-column

huangapple
  • 本文由 发表于 2020年3月16日 04:28:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/60697348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定