Для проекта I должен создать однонаправленную связь «один ко многим» с java EE, используя сущности. Идея проста: в интернет-магазине вы (пользователь) заказываете много товаров. При оформлении заказа эти продукты помещаются в таблицу базы данных (OrderProduct), а информация о вас также указывается в другой таблице (OrderUser). OrderProduct имеет первичный ключ (ID), основанный на идентификаторе пользователя (его собственный столбец идентификатора). Теперь у меня есть две сущности:
import javax.persistence.*;
import java.util.Objects;
@Entity
@Table(name = "OrderProduct", schema = "WebShopDatabase")
public class OrderProductEntity {
@Id
@Column(insertable = false, nullable = true)
private long id;
private int productId;
private double unitPrice;
private int quantity;
@Id
@Column(name = "ID", insertable = false, nullable = false)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Basic
@Column(name = "productID")
public int getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
@Basic
@Column(name = "unitPrice")
public double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Double unitPrice) {
this.unitPrice = unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
@Basic
@Column(name = "quantity")
public int getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrderProductEntity that = (OrderProductEntity) o;
return id == that.id &&
productId == that.productId &&
Double.compare(that.unitPrice, unitPrice) == 0 &&
quantity == that.quantity;
}
@Override
public int hashCode() {
return Objects.hash(id, productId, unitPrice, quantity);
}
}
Для базы данных OrderProduct. И:
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "OrderUser", schema = "WebShopDatabase")
public class OrderUserEntity {
@OneToMany(targetEntity = OrderProductEntity.class ,
cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
@JoinColumn (name = "ID",
nullable = false)
public Collection<OrderProductEntity> orderProduct;
@Id @GeneratedValue
private long id;
private String name;
private String city;
private String street;
private String phone;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Basic
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Basic
@Column(name = "CITY")
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Basic
@Column(name = "STREET")
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Basic
@Column(name = "PHONE")
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@OneToMany(targetEntity = OrderProductEntity.class ,
cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true)
@JoinColumn (name = "ID", referencedColumnName = "ID",
nullable = false)
public Collection<OrderProductEntity> getOrderProduct() {
return orderProduct;
}
public void setOrderProduct(Collection<OrderProductEntity> orderProduct) {
this.orderProduct = orderProduct;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrderUserEntity that = (OrderUserEntity) o;
return id == that.id &&
Objects.equals(name, that.name) &&
Objects.equals(city, that.city) &&
Objects.equals(street, that.street) &&
Objects.equals(phone, that.phone);
}
@Override
public int hashCode() {
return Objects.hash(id, name, city, street, phone);
}
}
Для OrderUser. И я добавляю к нему с помощью этого метода:
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Stateless(name = "OrderManagementEJB")
public class OrderManagementBean {
@PersistenceContext(unitName = "UsersPersistenceUnit")
private EntityManager em;
public OrderManagementBean() {
}
public void placeOrder(String name,
String city,
String street,
String phone,
ShoppingCartBean cart){
if(!(cart == null) && cart.getAmountProducts() != 0){
OrderUserEntity user = new OrderUserEntity();
user.setName(name);
user.setCity(city);
user.setStreet(street);
user.setPhone(phone);
List<OrderProductEntity> products = new ArrayList<>();
for(Map.Entry<ProductEntity, Integer> entry : cart.getAllProducts().entrySet()) {
OrderProductEntity product = new OrderProductEntity();
product.setProductId(entry.getKey().getProductId());
product.setUnitPrice(entry.getKey().getUnitCost());
product.setQuantity(entry.getValue());
product.setId(user.getId());
products.add(product);
}
user.setOrderProduct(products);
em.persist(user);
//em.flush();
}
}
}
Я получаю следующую ошибку в моем браузере:
The server encountered an internal error that prevented it from
fulfilling this request.
javax.ejb.EJBException: Transaction aborted
И следующий массивный блок ошибок в моем glassfi sh журналы сервера:
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.payara-p2): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`WebShopDatabase`.`OrderProduct`, CONSTRAINT `OrderProduct_OrderUser_ID_fk` FOREIGN KEY (`ID`) REFERENCES `OrderUser` (`ID`))
Error Code: 1452
Call: INSERT INTO WebShopDatabase.OrderProduct (PRODUCTID, QUANTITY, UNITPRICE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(kul.webshop.entities.OrderProductEntity@c46a3d0c)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:784)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:277)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:172)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:70)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:480)
... 41 more
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.payara-p2): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`WebShopDatabase`.`OrderProduct`, CONSTRAINT `OrderProduct_OrderUser_ID_fk` FOREIGN KEY (`ID`) REFERENCES `OrderUser` (`ID`))
Error Code: 1452
Call: INSERT INTO WebShopDatabase.OrderProduct (PRODUCTID, QUANTITY, UNITPRICE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(kul.webshop.entities.OrderProductEntity@c46a3d0c)
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:908)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:970)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:640)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:567)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2096)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:311)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:275)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:261)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:411)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:167)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:182)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:504)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:82)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:92)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:316)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:60)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:914)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:813)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:110)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:87)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2981)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1895)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1877)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1827)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:229)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:196)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:141)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4387)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1493)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1583)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3258)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:357)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:160)
... 43 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`WebShopDatabase`.`OrderProduct`, CONSTRAINT `OrderProduct_OrderUser_ID_fk` FOREIGN KEY (`ID`) REFERENCES `OrderUser` (`ID`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:127)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.sun.gjc.spi.jdbc40.ProfiledConnectionWrapper40$1.invoke(ProfiledConnectionWrapper40.java:437)
at com.sun.proxy.$Proxy363.executeUpdate(Unknown Source)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898)
... 75 more
]]
Error Code: 1452
Call: INSERT INTO WebShopDatabase.OrderProduct (PRODUCTID, QUANTITY, UNITPRICE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(kul.webshop.entities.OrderProductEntity@c46a3d0c)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:784)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:277)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:172)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:70)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:480)
... 41 more
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.4.payara-p2): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`WebShopDatabase`.`OrderProduct`, CONSTRAINT `OrderProduct_OrderUser_ID_fk` FOREIGN KEY (`ID`) REFERENCES `OrderUser` (`ID`))
Error Code: 1452
Call: INSERT INTO WebShopDatabase.OrderProduct (PRODUCTID, QUANTITY, UNITPRICE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(kul.webshop.entities.OrderProductEntity@c46a3d0c)
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:908)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:970)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:640)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:567)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2096)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:311)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:275)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:261)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:411)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:167)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:182)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:504)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:82)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:92)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:316)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:60)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:914)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:813)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:110)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:87)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2981)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1895)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1877)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1827)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:229)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:196)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:141)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4387)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1493)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1583)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3258)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:357)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:160)
... 43 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`WebShopDatabase`.`OrderProduct`, CONSTRAINT `OrderProduct_OrderUser_ID_fk` FOREIGN KEY (`ID`) REFERENCES `OrderUser` (`ID`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:127)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.sun.gjc.spi.jdbc40.ProfiledConnectionWrapper40$1.invoke(ProfiledConnectionWrapper40.java:437)
at com.sun.proxy.$Proxy363.executeUpdate(Unknown Source)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898)
... 75 more
]]
Код ошибки несколько сокращен из-за ограничения количества символов в StackOverflow. Я наклеил столько, сколько мог, сверху вниз.
Таблицы MySql:
Что создается с помощью:
`create table OrderProduct
(
ID bigint not null
primary key,
productID int not null,
unitPrice float not null,
quantity int not null,
constraint OrderProduct_OrderUser_ID_fk
foreign key (ID) references OrderUser (ID)
);`
и:
create table OrderUser
(
ID bigint auto_increment
primary key,
name varchar(50) not null,
city varchar(50) not null,
street varchar(255) not null,
phone varchar(25) not null
);
Они запускаются в контейнере Docker Toolbox (с чем у меня нет большого опыта), так что как только я найду, как правильно показать их здесь (вместо изображения), я сделаю это (предложения всегда приветствуются).
Я думаю, что в коде много неправильного, но поскольку Я совершенно новичок в этом, я действительно не знаю что. Мои предположения таковы: 1. Я неправильно добавляю обе таблицы 2. Обе таблицы, хотя одна из них имеет внешний ключ, полученный от другой, я не думаю, что они действительно «общаются» (я знаю, что это не так. слово, но не уверен, что это такое).
PS: Я работаю в intelliJ PS2: я знаю, что однонаправленное отношение - это плохо, и вы должны сделать многонаправленное, но меня специально попросили сделать это вот так.
РЕДАКТИРОВАТЬ: внесены изменения в журнал ошибок, поскольку он тоже изменился на что-то еще после повторного запуска с другими настройками.