我需要使用SpringBoot服务将excel的大约100,000行插入MySQL。这必须是用户上传excel的功能,然后我们才能存储记录。
当我不使用休眠批处理插入时,我可以插入记录,但是要花很多时间,因此我尝试使用休眠模式进行批处理插入。
以下是我的文件:
实体/模型:
@Entity
@Table(name="tariff")
public class Tariff implements Serializable {
@Id
@Column(name="tariff_id")
private Long tariffId;
@Column(name="provider_id")
private String providerId;
@Column(name="insurer_id")
private String insurerId;
@ManyToOne
@JoinColumn(name="tariff_type_id", referencedColumnName = "tariff_type_id")
private TariffType tariffType;
@ManyToOne
@JoinColumn(name="billing_group_id", referencedColumnName = "billing_group_id")
private BillingGroup billingGroup;
@ManyToOne
@JoinColumn(name="billing_sub_group_id", referencedColumnName = "billing_sub_group_id")
private BillingSubGroup billingSubGroup;
@ManyToOne
@JoinColumn(name="room_type_id", referencedColumnName = "room_type_id")
private RoomType roomType;
@ManyToOne
@JoinColumn(name="room_category_id", referencedColumnName = "room_category_id")
private RoomCategory roomCategory;
@NotNull
@Column(name="billing_code")
private String billingCode;
@Column(name="description")
private String description;
@NotNull
@Column(name="tariff_rate")
private Double tariffRate;
@Column(name="tariff_system")
private String tariffSystem;
@Column(name="inclusion")
private String inclusion;
@Column(name="exclusion")
private String exclusion;
@Column(name="tariff_year")
private String tariffYear;
}
resources / META-INF / persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="project_persistence" transaction-type="RESOURCE_LOCAL">
<!-- enable if you want xml mappings
<mapping-file>META-INF/orm.xml</mapping-file>
-->
<properties>
<!-- Configuring JDBC properties -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/databasename"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
<!-- Hibernate properties -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.show_sql" value="true"/>
<!-- batching size -->
<property name="hibernate.jdbc.batch_size" value="500"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<property name="hibernate.jdbc.batch_versioned_data" value="true"/>
</properties>
</persistence-unit>
我正在执行批量插入的功能:
private void saveTariffsFromExcel(DataFormatter dataFormatter, Sheet sheet, int totalRows, TariffType tariffType) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("project_persistence");
EntityManager em = emf.createEntityManager();
em.setFlushMode(FlushModeType.COMMIT);
BillingGroup billingGroup;
BillingSubGroup billingSubGroup;
RoomCategory roomCategory;
RoomType roomType;
Tariff tariff;
Long tariffId = tariffRepository.count()+1;
int batchSize = 500;
for (int i = 1; i < totalRows; i++) {
tariff = new Tariff();
Row row = sheet.getRow(i);
String tariffTypeStr = dataFormatter.formatCellValue(row.getCell(TARIFF_TYPE));
String billingCodeStr = dataFormatter.formatCellValue(row.getCell(BILLING_CODE));
String billingGroupStr = dataFormatter.formatCellValue(row.getCell(BILLING_GROUP));
String billingSubGroupStr = dataFormatter.formatCellValue(row.getCell(BILLING_SUB_GROUP));
String system = dataFormatter.formatCellValue(row.getCell(SYSTEM));
String description = dataFormatter.formatCellValue(row.getCell(DESCRIPTION));
String inclusions = dataFormatter.formatCellValue(row.getCell(INCLUSIONS));
String exclusions = dataFormatter.formatCellValue(row.getCell(EXCLUSIONS));
String roomTypeStr = dataFormatter.formatCellValue(row.getCell(ROOM_TYPE));
String roomCategoryStr = dataFormatter.formatCellValue(row.getCell(ROOM_CATEGORY));
String tariffRate = dataFormatter.formatCellValue(row.getCell(TARIFF));
tariff.setTariffId(tariffId);
if (tariffTypeStr != null && tariffTypeStr != "") {
tariffType.setTariffType(tariffTypeStr);
tariff.setTariffType(tariffType);
}
if (billingGroupStr != null && billingGroupStr != "") {
billingGroup = billingGroupRepository.getByBillingGroup(billingGroupStr);
tariff.setBillingGroup(billingGroup);
}
if (billingSubGroupStr != null && billingSubGroupStr != "") {
billingSubGroup = billingSubGroupRepository.getByBillingSubGroup(billingSubGroupStr);
tariff.setBillingSubGroup(billingSubGroup);
}
if (roomTypeStr != null && roomTypeStr != "") {
roomType = roomTypeRepository.getByRoomType(roomTypeStr);
tariff.setRoomType(roomType);
}
if (roomCategoryStr != null && roomCategoryStr != "") {
roomCategory = roomCategoryRepository.getByRoomCategory(roomCategoryStr);
tariff.setRoomCategory(roomCategory);
}
if (billingCodeStr != null && billingCodeStr != "") {
tariff.setBillingCode(billingCodeStr);
}
if (description != null && description != "") {
tariff.setDescription(description);
}
if (system != null && system != "") {
tariff.setTariffSystem(system);
}
if (tariffRate.isEmpty() || tariffRate == "") {
continue;
}
tariff.setTariffRate(Double.parseDouble(tariffRate));
if (inclusions != null && inclusions != "") {
tariff.setInclusion(inclusions);
}
if (exclusions != null && exclusions != "") {
tariff.setExclusion(exclusions);
}
tariff.setTariffYear("2018");
em.persist(tariff);
if (i % batchSize == 0 && i > 0) {
em.flush();
em.clear();
}
tariffId++;
}
em.getTransaction().commit();
}
但是,在第一次调用持久化时会导致以下错误:
org.hibernate.property.access.spi.PropertyAccessException:通过反射访问持久性[com.project.model.tariff]字段而访问字段[private java.lang.Long com.project.model.tariff.Tariff.tariffId]时出错.Tariff#tariffId]
控制台日志显示:
原因:java.lang.IllegalArgumentException:无法将java.lang.Long字段com.project.model.tariff.Tariff.tariffId设置为com.project.model.tariff.Tariff
我正在使用的版本: 弹簧靴:2.0.4 HibernateCore:5.2.17
我尝试搜索此错误,并通过了很多SO和博客链接,但是都没有运气。我对休眠很陌生。因此,任何参考或指导都将有所帮助。