JPA与很多孩子建立父/子关系

时间:2015-02-13 10:18:35

标签: postgresql ejb postgis jpa-2.1 hibernate-spatial

我正在尝试使用JPA方法创建将实体跟踪与子实体 TrackPoints 一起存储。但是,要将跟踪及其子 TrackPoints 存储的时间非常长 - 大约30秒。我尝试了 GenerationType.Identity GenerationType.SEQUENCE 。如果我也有Hibernate Spatial(Postgis)列,它会持续更长时间 - 大约60秒来存储父级和所有孩子。 JPA顺序发送一个插入,然后是另一个。我该如何优化呢?谁能告诉我主要问题是什么?

技术:

  • Wildfly 8.1,JPA 2.1(hibernate),Hibernate Spatial,EJB,JTA
  • PostgreSQL 9.3 + PostGis - 默认设置(只需从Ubuntu软件包安装)

Track.java

@Entity
@Table(name = "TRACKS")
public class Track implements Serializable {    
    @Id
    @Column(name = "track_id", nullable = false, unique = true)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @NotNull
    @NotEmpty
    @Size(min = 1, max = 100)
    @Column(nullable = false, length = 100)
    private String name;

    @Size(max = 200)
    @Column(nullable = false, length = 200)
    private String description;

    @OneToOne(optional = false)
    @JoinColumn(name = "userId", nullable = false)
    private User userOwner;

    @NotNull
    @NotEmpty
    @Column(nullable = false, length = 55)
    private String type;

    @NotNull
    private Boolean isShared;

    @OneToMany(mappedBy = "track")
    private List<TrackPoint> trackPoints;
}

TrackPoint.java

@Entity
@Table(name = "TRACK_POINTS")
public class TrackPoint implements Serializable {

    private static final long serialVersionUID = 8089601593251025235L;

    @Id
    @Column(name = "trackpoint_id", nullable = false, unique = true)
    @GeneratedValue(generator = "track_point_sequence", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "track_point_sequence", sequenceName = "track_point_sequence", allocationSize = 1000)
    private Long id;

    @NotNull
    private int trackSegment;

    @NotNull
    private double elevation;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date timeStamp;

    @NotNull
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name = "track_id")
    private Track track;

    /*Hibernate Spatial - Postgis field.
    @NotNull
    @Column(nullable = false)
    @Type(type = "org.hibernate.spatial.GeometryType")
    private Geometry location;*/
}

TrackService.java

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class TracksService implements ITracksService {

    @Inject
    private IDaoService dao;

    @Override
    public Long createTrack(GpxType gpx, String userId, String name, String desc) {
        // Map GPX to Track, TrackPoint object.
        track = dao.create(track);

    int batch_size = 50;

    int i = 0;

        for(TrackPoint point: track.getTrackPoints()) {
            dao.create(point);
            if(i++ % batch_size == 0) {
                dao.flush();
                dao.clear();
            }
        }

        return track.getId();

}

DaoService.java

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class DaoService implements IDaoService {

    @PersistenceContext()
    private EntityManager em;

    @Override
    public <T extends Serializable> T create(T t) {
        em.persist(t);
        return t;
    }
}

的persistence.xml

<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xsi:schemaLocation=
                     "http://xmlns.jcp.org/xml/ns/persistence
                          http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

    <persistence-unit name="postgisTourbookPU" transaction-type="JTA">

        <description>PostgresSQL database with PostGIS extension</description>
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>${tourbook.datasource.postgresql.jndi-name}</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <shared-cache-mode>NONE</shared-cache-mode>

        <properties>
            <!-- JPA properties -->
            <property name="javax.persistence.schema-generation.database.action"
                      value="drop-and-create"/>

            <!--            <property name="javax.persistence.schema-generation-target"
                                  value="database"/>-->

            <!-- Creation Schema Properties -->
            <property name="javax.persistence.schema-generation.create-source"
                      value="metadata"/>

            <!--            &lt;!&ndash; DDL Script location, when script is used &ndash;&gt;
                        <property name="javax.persistence.schema-generation.create-script-source"
                                    value="META-INF/create-script.sql"/>-->

            <!-- Drop Schema Properties -->
            <property name="javax.persistence.schema-generation.drop-source"
                      value="metadata"/>
            <!--            <property name="javax.persistence.schema-generation.drop-script-source"
                                  value="META-INF/drop-script.sql"/>-->

            <property name="javax.persistence.sql-load-script-source"
                                  value="META-INF/load-script.sql"/>

            <!-- JPA driver information -->
            <property name="javax.persistence.jdbc.driver"
                      value="org.postgresql.Driver"/>

            <!-- Hibernate properties -->
            <property name="hibernate.connection.characterEncoding"
                      value="UTF-8"/>

            <property name="hibernate.dialect"
                      value="org.hibernate.spatial.dialect.postgis.PostgisDialect"/>

            <property name="hibernate.default_schema"
                      value="public"/>

            <property name="hibernate.show_sql"
                      value="true"/>

            <property name="hibernate.jdbc.batch_size" value="50"/>

            <property name="hibernate.jdbc.fetch_size"
                      value="50"/>

            <property name="hibernate.order_inserts"
                      value="true"/>

            <property name="hibernate.order_updates"
                      value="true"/>

            <property name="hibernate.cache.use_query_cache"
                      value="false"/>

            <!-- Hibernate caching -->

        </properties>
    </persistence-unit>
</persistence>

被修改

所以我试过,在Hibernate中批量插入,但是我仍然可以节省30秒来保存2000点。

1 个答案:

答案 0 :(得分:0)

您正在插入包含所有孩子的父母。在这种情况下,Hibernate JPA确实可能很慢,但有一些提示可以提高性能 - 检查休眠批处理指南http://docs.jboss.org/hibernate/core/4.0/devguide/en-US/html/ch04.html - 我使用了hibernate.jdbc.batch_size参数(设置为例如50)

祝你好运           加布里埃尔