OpenJPA 事务异常
我正在尝试保留 BorderPoint 类的成员。持久化一定数量的对象后,openJPA 会抛出以下异常:
[错误] org.apache.openjpa.persistence.ArgumentException: 尝试将 id“0”分配给新实例“org.jason.mapmaker.shared.model.BorderPoint@” 3134a2”失败; L1 缓存中已存在具有此 id 的对象。在重用其 id 之前,您必须删除该对象(在上一个事务或当前事务中)。当水平或垂直映射的类使用自动增量应用程序标识并且不使用应用程序标识类的层次结构时,也会发生此错误。
持久化 BorderPoints 的方法接受 BorderPoint 对象的列表,并尝试将持久化分成批次。这是代码:
public void persistList(List<BorderPoint> objectList) throws RepositoryException {
EntityManager em = entityManagerFactory.createEntityManager();
try {
em.getTransaction().begin();
int i = 1;
for (BorderPoint bp : objectList) {
em.persist(bp);
if (i % 100 == 0) {
em.flush();
em.clear();
}
i++;
}
em.getTransaction().commit();
} catch (EntityExistsException ex) {
// need to log this somehow
//log.warning("persist() threw EntityExistsException: " + ex.getMessage());
ex.printStackTrace();
throw new RepositoryException(ex);
}
catch (Exception e) {
e.printStackTrace();
} finally {
em.close();
}
}
为了完整起见,这里是调用方法:
/**
* Cycle through and save the borderpoints saved in the Shapefile's geometry
*
* @param featureCollection
* @throws ServiceException
*/
private void saveBorderPoints(FeatureCollection featureCollection) throws ServiceException {
FeatureIterator iterator = featureCollection.features();
while (iterator.hasNext()) {
SimpleFeatureImpl feature = (SimpleFeatureImpl) iterator.next();
String geoId = (String) feature.getAttribute("GEOID10");
Location location = locationRepository.getByGeoId(geoId);
if (location == null) {
throw new ServiceException("saveBorderPoints() threw ServiceException due to null Location");
}
MultiPolygon multiPolygon = (MultiPolygon) feature.getDefaultGeometry();
Geometry geometry = multiPolygon.getBoundary();
// Create the result list. Set initial capacity size to number of actual points in the geometry to avoid some
// overhead when dealing with the list
List<BorderPoint> borderPointList = new ArrayList<BorderPoint>(geometry.getNumPoints());
// cycle through the coordinates to create the border points
Coordinate[] coordinates = geometry.getCoordinates();
for (Coordinate c : coordinates) {
BorderPoint borderPoint = new BorderPoint();
borderPoint.setLocation(location);
borderPoint.setLng(new BigDecimal(c.x));
borderPoint.setLat(new BigDecimal(c.y));
borderPointList.add(borderPoint);
}
try {
borderPointRepository.persistList(borderPointList);
} catch (RepositoryException e) {
throw new ServiceException("saveBorderPoints() threw RepositoryException", e);
}
}
iterator.close();
}
有什么想法吗?
编辑:
这是按照要求的 BorderPoint 类:
@Entity
@Table(name = "BORDERPOINT")
public class BorderPoint implements Serializable {
private Long id;
private Location location;
private BigDecimal lat;
private BigDecimal lng;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name="LAT")
public BigDecimal getLat() {
return lat;
}
public void setLat(BigDecimal lat) {
this.lat = lat;
}
@Column(name="LNG")
public BigDecimal getLng() {
return lng;
}
public void setLng(BigDecimal lng) {
this.lng = lng;
}
@ManyToOne(cascade = CascadeType.ALL, targetEntity = Location.class)
@JoinColumn(name="LOCATIONID")
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
I am trying to persist members of a class, BorderPoint. After persisting a certain number of objects, openJPA throws the following exception:
[ERROR] org.apache.openjpa.persistence.ArgumentException: Attempt to assign id "0" to new instance "org.jason.mapmaker.shared.model.BorderPoint@3134a2" failed; there is already an object in the L1 cache with this id. You must delete this object (in a previous transaction or the current one) before reusing its id. This error can also occur when a horizontally or vertically mapped classes uses auto-increment application identity and does not use a hierarchy of application identity classes.
The method to persist the BorderPoints accepts a List of BorderPoint objects and attempts to break the persist into batches. Here is the code:
public void persistList(List<BorderPoint> objectList) throws RepositoryException {
EntityManager em = entityManagerFactory.createEntityManager();
try {
em.getTransaction().begin();
int i = 1;
for (BorderPoint bp : objectList) {
em.persist(bp);
if (i % 100 == 0) {
em.flush();
em.clear();
}
i++;
}
em.getTransaction().commit();
} catch (EntityExistsException ex) {
// need to log this somehow
//log.warning("persist() threw EntityExistsException: " + ex.getMessage());
ex.printStackTrace();
throw new RepositoryException(ex);
}
catch (Exception e) {
e.printStackTrace();
} finally {
em.close();
}
}
Just for completeness, here is the calling method:
/**
* Cycle through and save the borderpoints saved in the Shapefile's geometry
*
* @param featureCollection
* @throws ServiceException
*/
private void saveBorderPoints(FeatureCollection featureCollection) throws ServiceException {
FeatureIterator iterator = featureCollection.features();
while (iterator.hasNext()) {
SimpleFeatureImpl feature = (SimpleFeatureImpl) iterator.next();
String geoId = (String) feature.getAttribute("GEOID10");
Location location = locationRepository.getByGeoId(geoId);
if (location == null) {
throw new ServiceException("saveBorderPoints() threw ServiceException due to null Location");
}
MultiPolygon multiPolygon = (MultiPolygon) feature.getDefaultGeometry();
Geometry geometry = multiPolygon.getBoundary();
// Create the result list. Set initial capacity size to number of actual points in the geometry to avoid some
// overhead when dealing with the list
List<BorderPoint> borderPointList = new ArrayList<BorderPoint>(geometry.getNumPoints());
// cycle through the coordinates to create the border points
Coordinate[] coordinates = geometry.getCoordinates();
for (Coordinate c : coordinates) {
BorderPoint borderPoint = new BorderPoint();
borderPoint.setLocation(location);
borderPoint.setLng(new BigDecimal(c.x));
borderPoint.setLat(new BigDecimal(c.y));
borderPointList.add(borderPoint);
}
try {
borderPointRepository.persistList(borderPointList);
} catch (RepositoryException e) {
throw new ServiceException("saveBorderPoints() threw RepositoryException", e);
}
}
iterator.close();
}
Any ideas out there?
EDIT:
Here is the BorderPoint class, as requested:
@Entity
@Table(name = "BORDERPOINT")
public class BorderPoint implements Serializable {
private Long id;
private Location location;
private BigDecimal lat;
private BigDecimal lng;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name="LAT")
public BigDecimal getLat() {
return lat;
}
public void setLat(BigDecimal lat) {
this.lat = lat;
}
@Column(name="LNG")
public BigDecimal getLng() {
return lng;
}
public void setLng(BigDecimal lng) {
this.lng = lng;
}
@ManyToOne(cascade = CascadeType.ALL, targetEntity = Location.class)
@JoinColumn(name="LOCATIONID")
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论