openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jason Ferguson <fergusonja...@gmail.com>
Subject Help Persisting a List
Date Tue, 05 Apr 2011 21:28:19 GMT
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

Mime
View raw message