我在申请中被这个问题困扰了几天。
我有两个表event
和guest
相关的ManyToMany
关系,由表event_guest
映射。由于我需要访问连接表以存储额外的属性,我还有一个该表的实体,并且在主要实体中有两个ManyToOne
具有相应的OneToMany
关系。
以下是相关代码:
事件实体
@Entity
@Table ( name = "event" )
public class EventEntity implements Serializable {
@Id
@Column ( name = "event_id", insertable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
@OneToMany(mappedBy = "event")
private List<EventGuestEntity> eventGuest;
...
}
访客实体
@Entity
@Table ( name = "guest" )
public class GuestEntity implements Serializable {
@Id
@Column(name = "guest_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
...
@OneToMany(mappedBy = "guest")
private List<EventGuestEntity> eventGuest;
...
}
加入表格实体
@Entity
@Table(name = "event_guest")
public class EventGuestEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "event_guest_id")
private Long id;
...
@ManyToOne
@NotNull
@JoinColumn(name = "event_id")
private EventEntity event;
@ManyToOne
@NotNull
@JoinColumn(name = "guest_id")
private GuestEntity guest;
...
}
这里实际上将guest虚拟机关联到事件的EJB代码:
@Stateless
public class GuestBean implements GuestBeanLocal {
private static final Logger logger = LogManager.getLogger(GuestBean.class.getName());
private GuestEntity guestEntity;
private EventEntity eventEntity;
private EventGuestEntity eventGuestEntity;
@PersistenceContext
private EntityManager em;
public Boolean associateGuestToEvent(Long eventId, int guestId) {
guestEntity = em.find(GuestEntity.class, guestId);
eventEntity = em.find(EventEntity.class, eventId);
try {
Query q = em.createNamedQuery("getEventGuestByIds").setParameter("event", eventId).setParameter("guest", guestId);
eventGuestEntity = (EventGuestEntity) q.getSingleResult();
} catch (NoResultException e) {
eventGuestEntity = null;
}
if (eventGuestEntity == null) {
eventGuestEntity = new EventGuestEntity();
eventGuestEntity.setGuest(guestEntity);
eventGuestEntity.setEvent(eventEntity);
List<EventGuestEntity> listFromGuest = guestEntity.getEventGuest();
listFromGuest.add(eventGuestEntity);
List<EventGuestEntity> listFromEvent = eventEntity.getEventGuest();
listFromEvent.add(eventGuestEntity);
try {
em.merge(eventGuestEntity);
em.merge(eventEntity);
em.merge(guestEntity);
em.flush();
em.refresh(eventEntity);
em.refresh(guestEntity);
return true;
} catch (PersistenceException e) {
logger.debug("Error while adding guest entity to event entity list.");
return false;
}
} else {
return true;
}
到目前为止,一切似乎都很好。客人可以与事件相关联,然后与事件分离,然后重新关联,一切正常。
直到我用最小的负载量来强调应用程序。如果我用JMeter用2个线程测试它就足以让事情开始失败。
这就是它变得奇怪的地方。将客人与活动相关联的实际功能就像魅力一样。但是,无论JMeter测试中的下一个是什么,都会因为这样的唯一约束违规而失败:
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '40-3' for key 'uq_event_id_guest_id_idx'
Error Code: 1062
Call: INSERT INTO event_guest (event_id, guest_id) VALUES (?, ?)
bind => [40, 3]
这使得与guest虚拟机关联事件(甚至不会触及guest虚拟机实体或连接表实体)无关的功能失败。我甚至改变了测试的顺序,看它是否会破坏任何功能,看起来它们中的任何一个都表现出相同的行为。有一点我注意到,如果我在JMeter中的请求之间添加一个恒定的延迟,问题就会消失。 100毫秒足以使其正常工作。
我启用了eclipselink日志记录并将其设置为ALL级别。我查看了生成的日志,但没有找到任何有罪的东西。现在,我唯一的想法是测试其他JPA提供程序和/或其他应用程序服务器,以隔离它是我的应用程序还是这两个组件之一。但我敢打赌这是我的代码,所以我在这里寻求帮助。