Datanucleus - 使用复合键时每隔一行为空白

Datanucleus - Every second row is blank when composite keys used

我有一个 MySQL table,具有以下架构和数据:

CREATE TABLE IF NOT EXISTS `orderdetails` (
  `orderNumber` int(11) NOT NULL,
  `productCode` varchar(15) NOT NULL,
  `quantityOrdered` int(11) NOT NULL,
  `priceEach` double NOT NULL,
  `orderLineNumber` smallint(6) NOT NULL,
  PRIMARY KEY (`orderNumber`,`productCode`),
  KEY `productCode` (`productCode`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `orderdetails` (`orderNumber`, `productCode`, `quantityOrdered`, `priceEach`, `orderLineNumber`) VALUES
(10100, 'S18_1749', 30, 136, 3),
(10100, 'S18_2248', 50, 55.09, 2),
(10100, 'S18_4409', 22, 75.46, 4),
(10100, 'S24_3969', 49, 35.29, 1),
(10101, 'S18_2325', 25, 108.06, 4),
(10101, 'S18_2795', 26, 167.06, 1),
(10101, 'S24_1937', 45, 32.53, 3),
(10101, 'S24_2022', 46, 44.35, 2),
(10102, 'S18_1342', 39, 95.55, 2),
(10102, 'S18_1367', 41, 43.13, 1);

ALTER TABLE `orderdetails`
  ADD CONSTRAINT `orderdetails_ibfk_2` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`),
  ADD CONSTRAINT `orderdetails_ibfk_1` FOREIGN KEY (`orderNumber`) REFERENCES `orders` (`orderNumber`);

如果我尝试通过以下方式映射这些实体:

方式一

使用 @IdClass 注释。我有一个 OrderDetailsId class:

public class OrderDetailsId implements Serializable {    
    private int orderNumber;    
    private String productCode;   

    public int hashCode() {
        return (int) productCode.hashCode() + orderNumber;
    }    

    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof OrderDetailsId)) return false;
        if (obj == null) return false;
        OrderDetailsId pk = (OrderDetailsId) obj;
        return pk.orderNumber == orderNumber && pk.productCode.equals(productCode);
    }
}

还有一个 OrderDetails class:

@IdClass(OrderDetailsId.class)
@Entity
@Table(name = "ORDERDETAILS")
public class OrderDetails {

    @Id
    @Column(name = "ORDERNUMBER")
    private int orderNumber;

    @Id
    @Column(name = "PRODUCTCODE")
    private String productCode;

    @Column(name = "quantityOrdered")
    private int quantityOrdered;

    @Column(name = "priceEach")
    private double priceEach;

    @Column(name = "orderLineNumber")
    private int orderLineNumber;

}

当我尝试将其中一些对象保存到 .xls 文件中时,它 运行 成功了,但是每隔一行都是空白的。方法如下:

public void exportSomeToXls() {
    OrderDetails o1 = getOrderDetails("S18_1749", 10100);
    OrderDetails o2 = getOrderDetails("S18_1750", 10101);
    OrderDetails o3 = getOrderDetails("S18_1751", 10102);
    OrderDetails o4 = getOrderDetails("S18_1752", 10103);
    OrderDetails o5 = getOrderDetails("S18_1753", 10104);
    EntityTransaction tx = xlsManager.getTransaction();
    tx.begin();
    xlsManager.persist(o1);
    xlsManager.persist(o2);
    xlsManager.persist(o3);
    xlsManager.persist(o4);
    xlsManager.persist(o5);
    tx.commit();
}

private OrderDetails getOrderDetails(String productCode, int orderNumber) {
    OrderDetails o1 = new OrderDetails();
    o1.setProductCode(productCode);
    o1.setOrderNumber(orderNumber);
    o1.setOrderLineNumber(1);
    o1.setPriceEach(136);
    o1.setQuantityOrdered(30);
    return o1;
}

结果:

我也试过docs里面写的东西,但是数据之间还是有一个空行

如果我 运行 这个方法是在 MySQL 数据存储上,而不是在 .xls 数据存储上,行保存到数据库中。

方式 2

我试过的另一种方法是使用 @Embeddable 注释和 "Embedded" 键。 OrderDetailsId class:

@Embeddable
public class OrderDetailsId implements Serializable {

    private int orderNumber;

    private String productCode;

    public int hashCode() {
        return (int) productCode.hashCode() + orderNumber;
    }

    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof OrderDetailsId)) return false;
        if (obj == null) return false;
        OrderDetailsId pk = (OrderDetailsId) obj;
        return pk.orderNumber == orderNumber && pk.productCode.equals(productCode);
    }
}

OrderDetails class:

@Entity
@Table(name = "ORDERDETAILS")
public class OrderDetails {

    private OrderDetailsId primaryKey;

    @Column(name = "quantityOrdered")
    private int quantityOrdered;

    @Column(name = "priceEach")
    private double priceEach;

    @Column(name = "orderLineNumber")
    private int orderLineNumber;

    @EmbeddedId
    public OrderDetailsId getPrimaryKey(){
        return primaryKey;
    }
}

以及执行持久化的方法:

public void exportSomeToXls() {
    OrderDetails o1 = getOrderDetails("S18_1749", 10100);
    OrderDetails o2 = getOrderDetails("S18_1750", 10101);
    OrderDetails o3 = getOrderDetails("S18_1751", 10102);
    OrderDetails o4 = getOrderDetails("S18_1752", 10103);
    OrderDetails o5 = getOrderDetails("S18_1753", 10104);
    EntityTransaction tx = xlsManager.getTransaction();
    tx.begin();
    xlsManager.persist(o1);
    xlsManager.persist(o2);
    xlsManager.persist(o3);
    xlsManager.persist(o4);
    xlsManager.persist(o5);
    tx.commit();
}

private OrderDetails getOrderDetails(String productCode, int orderNumber) {
    OrderDetailsId id = new OrderDetailsId();
    id.setOrderNumber(orderNumber);
    id.setProductCode(productCode);

    OrderDetails o1 = new OrderDetails();
    o1.setPrimaryKey(id);
    o1.setOrderLineNumber(1);
    o1.setPriceEach(136);
    o1.setQuantityOrdered(30);
    return o1;
}

在这种情况下,我在运行时遇到了 NPE,查看堆栈跟踪:

java.lang.NullPointerException
    at org.datanucleus.store.excel.fieldmanager.StoreFieldManager.<init>(StoreFieldManager.java:90)
    at org.datanucleus.store.excel.ExcelPersistenceHandler.insertObject(ExcelPersistenceHandler.java:153)
    at org.datanucleus.store.AbstractPersistenceHandler.insertObjects(AbstractPersistenceHandler.java:71)
    at org.datanucleus.flush.FlushNonReferential.flushDeleteInsertUpdateGrouped(FlushNonReferential.java:190)
    at org.datanucleus.flush.FlushNonReferential.execute(FlushNonReferential.java:60)
    at org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:3987)
    at org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:3932)
    at org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4098)
    at org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:683)
    at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:388)
    at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:277)
    at org.datanucleus.api.jpa.JPAEntityTransaction.commit(JPAEntityTransaction.java:98)
    at com.example.poc.daos.OrderDetailsDao.exportSomeToXls(OrderDetailsDao.java:48)
    at com.example.poc.Main.main(Main.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.codehaus.mojo.exec.ExecJavaMojo.run(ExecJavaMojo.java:290)
    at java.lang.Thread.run(Thread.java:745)

问题

有什么方法可以将 DataNucleus 与复合键一起使用吗?

这是一个错误。已报告,将在下一个版本中修复。参见:

http://www.datanucleus.org/servlet/forum/viewthread_thread,7835_offset,0#37884

感谢@Neil Stockton 的帮助!