插入时如何忽略重复行

时间:2015-11-30 09:19:02

标签: java mysql sql-server hibernate jpa

我使用hibernate-jpa-2.1-api。我需要一些功能。

我每分钟解析一个文件并将数据插入MSSQL DB。我需要跳过重复的行。例如,在12:00,我的文件中有300行。我解析每一个并插入300行。一分钟后(12:01)我的文件包含500行。我解析它,我想只插入200个新行,而不是旧的300行。

在程序的旧实现中,我使用了SQL insert并且没有使用ORM。

这是我的旧SQL查询:

insert /*+ ignore_row_on_dupkey_index(avaya_cm_cdr, i_avaya_cm_cdr_nodub) */  into avaya_cm_cdr(acmcdr_id, cdrdate, cdrtime, secdur, condcode, attdconsole, codeused, outcrtid, codedial, dialednum, intrkcode, incrtid, callingnum, vdn, bcc, ppm, acctcode, authcode) values(seq_acmcdr_id.nextval, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

这是我使用ORM的新插件:

em = Persistence.createEntityManagerFactory("COLIBRI").createEntityManager();
public void insertAVAYAcmCDRs(List<AvayaCmCdr> cdrList) {
    em.getTransaction().begin();
    for (AvayaCmCdr aCdrList : cdrList) {
        em.persist(aCdrList);
    }
    em.getTransaction().commit();
}

如何将模拟功能ignore_row_on_dupkey_index用于ORM?

P.S。在旧的实现中,我使用了Oracle DB。

1 个答案:

答案 0 :(得分:0)

数据库样式选项

Hibernate不提供为其insert into语句添加选项。而且我不知道MS SQL是否有相同的选项。

但是如果你找到这样的选项,你可以拦截插入语句并自己添加:

public class IgnoreRowOnDupInterceptor extends EmptyInterceptor {

  public String onPrepareStatement(String sql) {
    if (sql.startsWith("insert into avaya_cm_cdr") {
      return sql.replace("insert into", 
        "insert /*+ ignore_row_on_dupkey_index(avaya_cm_cdr, i_avaya_cm_cdr_nodub) */ into");
    }
    return sql;
  }

} 

您需要在persistence.xml

中声明此拦截器
<property name="hibernate.ejb.interceptor" value="...IgnoreRowOnDupInterceptor" />

JPA样式选项

您可以记住上次解析的最后一行(或从数据库中检索它)并跳过该行直到该行。在这种情况下,您甚至可以节省一次又一次地解析每个现有项目的时间。

从我的观点来看,这是JPA方式,因为您通常仅将数据库用作存储,并将业务逻辑保留在(Java)应用程序中。