我正在尝试使用JPA方法创建将实体跟踪与子实体 TrackPoints 一起存储。但是,要将跟踪及其子 TrackPoints 存储的时间非常长 - 大约30秒。我尝试了 GenerationType.Identity 和 GenerationType.SEQUENCE 。如果我也有Hibernate Spatial(Postgis)列,它会持续更长时间 - 大约60秒来存储父级和所有孩子。 JPA顺序发送一个插入,然后是另一个。我该如何优化呢?谁能告诉我主要问题是什么?
技术:
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"/>
<!-- <!– DDL Script location, when script is used –>
<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点。
答案 0 :(得分:0)
您正在插入包含所有孩子的父母。在这种情况下,Hibernate JPA确实可能很慢,但有一些提示可以提高性能 - 检查休眠批处理指南http://docs.jboss.org/hibernate/core/4.0/devguide/en-US/html/ch04.html - 我使用了hibernate.jdbc.batch_size参数(设置为例如50)
祝你好运 加布里埃尔