我正在尝试使用Hibernate 4.3和SQL-Server 2014对仅尚未存储的实体执行批量插入表中。 我创建了一个简单的表,其中的主键定义为忽略重复的键
@app.route('/Search', methods=['POST', 'GET'])
@login_required
def Search():
if request.method == 'POST':
query_result = google_places.nearby_search(
lat_lng={'lat':31.7917, 'lng' : 7.0926},
radius=500,
types=[types.TYPE_SHOPPING_MALL] or [types.TYPE_STORE])`
if query_result.has_attributions:
print(query_result.html_attributions)
for place in query_result.places:
place.get_details()
place_name = place.name
print(place.name)
place_rating = place.rating
print(place.rating)
place_location = place.get_location
print(place.get_location)
for photo in place.photos:
photo.get(maxheight=500, maxwidth=500)
photo.mimetype
photo.url
photo.filename
photo.data
return render_template('Search.html', place_name, place_rating, place_location)
else:
return render_template('Search.html')```
#Note: i am new to python in general
尝试通过StatelessSession插入方法执行批量插入,如果一个或多个实体已经存储到数据库表中,则批量插入可能会失败:Hibernate抛出StaleStateException:
create table items
(
itemid uniqueidentifier not null,
itemname nvarchar(30) not null,
)
alter table items add constraint items_pk primary key ( itemid ) with ( ignore_dup_key = on );
批处理语句完成后,由于忽略重复键,Hibernate将对返回的行数进行检查,该计数与预期的不同。
对于JDBC,使用预处理语句执行批处理插入,将跳过已存储到目标表中的实体,但正确保存新实体。
如何将Hibernate配置为忽略现有数据执行批量插入,或者不对受影响的行进行检查?
非常感谢
更新#1
作为一种解决方法,即使发生重复的插入,也要强制受影响的行数,我创建了以下Hibernate Interceptor:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:63)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:144)
at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:123)
at it.test.testingestion.HibernateStatelessSessionPersisterImpl.persistData(HibernateStatelessSessionPersisterImpl.java:18)
at it.test.testingestion.App.main(App.java:76)
拦截器在创建新实例时会创建一个插入新记录的新临时表。 当一条插入语句被拦截时,如果没有行受到插入语句的影响,则将更新保存到实例临时表中的记录:如果插入了重复的实体并且没有StatelessSessionImpl异常,这将使Hibernate有关返回的行事件抛出。
显然,此技巧的缺点是对未插入表中的每一行执行额外更新的成本。
有没有人知道一种更好的方法,该方法不影响插入性能,而是将实体插入到使用Hibernate忽略重复条目的表中?
谢谢
答案 0 :(得分:0)
为了获得更好的性能,我更喜欢使用JDBCBatchUpdate
方法1:
在过滤新记录时,记录数将不受限制。因此,您可以在实体层中指定关联映射,并可以执行Hibernate批处理插入或JDBC批处理更新。
方法2: 使用本机SQl查询
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//get Connction from Session
session.doWork(new Work() {
@Override
public void execute(Connection conn) throws SQLException {
PreparedStatement pstmt = null;
try{
String sqlInsert = "insert into tbl(name) values (?) ";
pstmt = conn.prepareStatement(sqlInsert );
int i=0;
for(String name : list){
pstmt .setString(1, name);
pstmt .addBatch();
//20 : JDBC batch size
if ( i % 20 == 0 ) {
pstmt .executeBatch();
}
i++;
}
pstmt .executeBatch();
}
finally{
pstmt .close();
}
}
});
tx.commit();
session.close();