In addition to Mike's question, I'd like to know what version of OpenJPA you are using. I've seen this issue before and fixed it with JIRA OJ-1665. I did notice your BorderPoint class uses an '@GeneratedValue' so it appears you are using auto generated values as described in OJ-1665. This JIRA was recently fixed in OpenJPA versions 1.2.x/1.3.x/2.0.x so unless you have a recent build, you've not picked up the change yet.
Thanks, Heath On Wed, Apr 6, 2011 at 10:30 AM, Michael Dick <[email protected]>wrote: > I'm going to ask Risk's standard question, how are you doing enhancement? > > Can you narrow down the scope of the problem, e.g. does the problem happen > on every insert, or is it something that only happens when the list is > large? > > -mike > > > On Tue, Apr 5, 2011 at 4:28 PM, Jason Ferguson <[email protected] > >wrote: > > > I have two Entities: Location and BorderPoint. Location contains a > > List of BorderPoint, with a bidirectional mapping between them. The > > list containing the BorderPoints can be quite large (9,000 is not > > unheard of). Unfortunately, the attempt to persist a list fails with > > 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. > > > > > > I read the data from an ESRI Shapefile in two passes. The first pass > > persists all locations in the Shapefile, then I come back and read the > > geometry stored in the Shapefile into the BorderPoint list. The code > > to actually persist the List of BorderPoint objects tries to break up > > the commit into batches of 100. > > > > The call to persist the Locations and BorderPoint objects looks like > this: > > > > for (String typeName : typeNames) { > > > > FeatureSource featureSource; > > FeatureCollection featureCollection; > > > > try { > > featureSource = dataStore.getFeatureSource(typeName); > > featureCollection = featureSource.getFeatures(); > > > > saveLocations(featureCollection); > > saveBorderPoints(featureCollection); > > > > } catch (IOException e) { > > throw new ServiceException("processShapefile() threw > > IOException", e); > > } > > > > } > > > > The method to persist the borderPoints looks like this: > > > > 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(); > > } > > > > and > > > > @Transactional > > 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(); > > } > > } > > > > Finally, here is the code for the BorderPoint class: > > > > @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; > > } > > } > > > > Can anyone help me? > > > > Jason > > >
