【问题标题】:ManyToMany EclipseLink Insert多对多 EclipseLink 插入
【发布时间】:2013-09-21 20:54:39
【问题描述】:

我认为真正的问题是我无法获得最近持续存在的实体的 id(我不知道如何)。我正在使用 eclipseLink 2.1 和 mysql 5.1.7,所以我离开了我的实体类

多对多的连接表,是ProductosVentas;对不起西班牙语命名

请帮帮我

这是我的脚本

public static void main(String args[]) {
    EntityManager em = EclipseLinkUtil.getEntityManagerFactory();
    em.getTransaction().begin();
    try {
        Query query = em
            .createQuery("from Productos p where p.nombre like 'Lavado de motor' ");
        Productos selledItem = (Productos) query.getSingleResult();
        query = em.createNativeQuery("select curdate() ");
        java.sql.Date sellingDate = (Date) query.getSingleResult();
        Ventas v1 = new Ventas();
        v1.setCondicionventaIdcondicionventa(new Condicionventa(1));
        v1.setFecha(sellingDate);
        List<Productosventas> selledItemTableList = new ArrayList<>();
        v1.setProductosventasCollection(selledItemTableList);
        Productosventas p = new Productosventas();
        p.setVentas(v1);
        p.setCantidad(1);
        p.setProductos(selledItem);
        selledItemTableList.add(p);
        em.persist(v1);
        em.persist(p);
        em.getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        em.getTransaction().rollback();
    } finally {
        em.close();
    }
}

错误

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:

列“ventas_idventa”不能为空 错误代码:1048 调用: INSERT INTO productosventas (cantidad, ventas_idventa, productos_idProductos, PriceModifiers_idPriceModifier) VALUES (?, ?, ?,?) bind => [绑定4个参数]

那些是我的实体

@Entity
@Table(name = "productos")
@XmlRootElement
public class Productos implements Serializable {

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "productos")
    private Collection<Productosventas> productosventasCollection;
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "idProductos")
    private Integer idProductos;
    // [properties]
    @JoinColumn(name = "PriceModifiers_idPriceModifier",
            referencedColumnName = "idPriceModifier")
    @ManyToOne(optional = false)
    private Pricemodifiers priceModifiersidPriceModifier;
    @JoinColumn(name = "AreaServicio_idAreaServicio",
            referencedColumnName = "idAreaServicio")
    @ManyToOne(optional = false)
    private Areaservicio areaServicioidAreaServicio;
    @JoinColumn(name = "formaventa_idFormaVenta",
            referencedColumnName = "idFormaVenta")
    @ManyToOne(optional = false)
    private Formaventa formaventaidFormaVenta;

    // geters and setters
    @XmlTransient
    public Collection<Productosventas> getProductosventasCollection() {
        return productosventasCollection;
    }

    public void setProductosventasCollection(
            Collection<Productosventas> productosventasCollection) {
        this.productosventasCollection = productosventasCollection;
    }
}

@Entity
@Table(name = "ventas")
@XmlRootElement
public class Ventas implements Serializable {

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "ventas")
    private Collection<Productosventas> productosventasCollection;
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "idventa")
    private Integer idventa;
    @Column(name = "fecha")
    @Temporal(TemporalType.TIMESTAMP)
    private Date fecha;
    @JoinColumn(name = "condicionventa_idcondicionventa",
            referencedColumnName = "idcondicionventa")
    @ManyToOne(optional = false)
    private Condicionventa condicionventaIdcondicionventa;
    @JoinColumn(name = "climas_idclimas", referencedColumnName = "idclimas")
    @ManyToOne(optional = false)
    private Climas climasIdclimas;
    @JoinColumn(name = "cliente_idcliente", referencedColumnName = "idcliente")
    @ManyToOne(optional = false)
    private Cliente clienteIdcliente;
    @JoinColumn(name = "cars_numberplate", referencedColumnName = "numberplate")
    @ManyToOne(optional = false)
    private Cars carsNumberplate;

    // getters and setters
    @XmlTransient
    public Collection<Productosventas> getProductosventasCollection() {
        return productosventasCollection;
    }

    public void setProductosventasCollection(
            Collection<Productosventas> productosventasCollection) {
        this.productosventasCollection = productosventasCollection;
    }
}

@Entity
@Table(name = "productosventas")
@XmlRootElement
public class Productosventas implements Serializable {

    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected ProductosventasPK productosventasPK;
    @Column(name = "cantidad")
    private Integer cantidad;
    @JoinColumn(name = "PriceModifiers_idPriceModifier",
            referencedColumnName = "idPriceModifier")
    @ManyToOne(optional = false)
    private Pricemodifiers priceModifiersidPriceModifier;
    @JoinColumn(name = "ventas_idventa", referencedColumnName = "idventa",
            insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private Ventas ventas;
    @JoinColumn(name = "productos_idProductos",
            referencedColumnName = "idProductos", insertable = false,
            updatable = false)
    @ManyToOne(optional = false)
    private Productos productos;

    public Productosventas() {}

    public Productosventas(ProductosventasPK productosventasPK) {
        this.productosventasPK = productosventasPK;
    }

    public Productosventas(int ventasIdventa, int productosidProductos) {
        this.productosventasPK = new ProductosventasPK(ventasIdventa,
            productosidProductos);
    }

    public ProductosventasPK getProductosventasPK() {
        return productosventasPK;
    }

    public void setProductosventasPK(ProductosventasPK productosventasPK) {
        this.productosventasPK = productosventasPK;
    }

    // geters and setters
}

@Embeddable
public class ProductosventasPK implements Serializable {

    @Basic(optional = false)
    @Column(name = "ventas_idventa")
    private int ventasIdventa;
    @Basic(optional = false)
    @Column(name = "productos_idProductos")
    private int productosidProductos;

    public ProductosventasPK() {}

    public ProductosventasPK(int ventasIdventa, int productosidProductos) {
        this.ventasIdventa = ventasIdventa;
        this.productosidProductos = productosidProductos;
    }

    // geters and setters

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (int) ventasIdventa;
        hash += (int) productosidProductos;
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are
        // not set
        if (!(object instanceof ProductosventasPK)) {
            return false;
        }
        ProductosventasPK other = (ProductosventasPK) object;
        if (this.ventasIdventa != other.ventasIdventa) {
            return false;
        }
        if (this.productosidProductos != other.productosidProductos) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "tiendita.entities.ProductosventasPK[ ventasIdventa="
            + ventasIdventa + ", productosidProductos=" + productosidProductos
            + " ]";
    }
}

编辑

我尝试先刷新(感谢 chris),但它看起来丑陋、冗长且不合时宜……这似乎是一种奇特的方式,但它用休眠方式编写太糟糕了,我正在使用 eclipselink。我希望这段代码也可以这样写。

session.beginTransaction();

Stock stock = new Stock();
stock.setStockCode("7052");
stock.setStockName("PADINI");

Category category1 = new Category("CONSUMER", "CONSUMER COMPANY");
//new category, need save to get the id first
session.save(category1);

StockCategory stockCategory = new StockCategory();
stockCategory.setStock(stock);
stockCategory.setCategory(category1);
stockCategory.setCreatedDate(new Date()); //extra column
stockCategory.setCreatedBy("system"); //extra column

stock.getStockCategories().add(stockCategory);

session.save(stock);

session.getTransaction().commit();

这似乎很简陋

EntityManager em = EclipseLinkUtil.getEntityManagerFactory();

em.getTransaction().begin();
try {

    Query query = em.createQuery("from Productos p where p.nombre like 'Lavado de motor' ");
    Productos selledItem = (Productos) query.getSingleResult();

    query = em.createNativeQuery("select curdate() ");
    java.sql.Date sellingDate = (Date) query.getSingleResult();

    Ventas v1 = new Ventas();
    v1.setCondicionventaIdcondicionventa(new Condicionventa(1));
    v1.setFecha(sellingDate);

    List<Productosventas> selledItemTableList = new ArrayList<>();
    v1.setProductosventasCollection(selledItemTableList);
    em.persist(v1);
    em.flush();

    Productosventas p = new Productosventas();
    p.setProductosventasPK(new ProductosventasPK(v1.getIdventa(), selledItem.getIdProductos()));
    p.setCantidad(1);
    p.setProductos(selledItem);
    selledItemTableList.add(p);

    p = new Productosventas();
    p.setProductosventasPK(new ProductosventasPK(v1.getIdventa(), selledItem.getIdProductos()));
    p.setCantidad(2);
    selledItemTableList.add(p);
    selledItem.setProductosventasCollection(selledItemTableList);

    em.persist(selledItem);
    em.getTransaction().commit();

} catch (Exception e) {
    e.printStackTrace();
    em.getTransaction().rollback();
} finally {
    em.close();
}

我最讨厌的是这个

    em.persist(v1);
    em.flush();
    Productosventas p = new Productosventas();
    p.setProductosventasPK(new ProductosventasPK(v1.getIdventa(), selledItem.getIdProductos()));
    p.setCantidad(1);
    p.setProductos(selledItem);

第二次修改

public class ProductosventasPK implements Serializable {

     private int ventas;

    private int productos;

    public ProductosventasPK() {
    }

    public ProductosventasPK(int ventasIdventa, int productosidProductos) {
        this.ventas = ventasIdventa;
        this.productos = productosidProductos;
    }
    // geters and setters

    @Override
    public String toString() {
        return "tiendita.entities.ProductosventasPK[ ventasIdventa=" + ventas
            + ", productosidProductos=" + productos + " ]";
    }

}

@Entity
@IdClass(ProductosventasPK.class)
@Table(name = "productosventas", catalog = "tiendita", schema = "")
public class Productosventas implements Serializable {
@JoinColumn(name = "productos_idProductos", referencedColumnName = "idProductos",
        insertable = true, updatable = true)
    @Id
    @ManyToOne(optional = false, cascade = CascadeType.MERGE)
    private Productos productos;
    @JoinColumn(name = "ventas_idventa", referencedColumnName = "idventa",
        insertable = true, updatable = true)
    @Id
    @ManyToOne(optional = false)
    private Ventas ventas;

    ProductosventasPK productosventasPK;
//important parts

}

其余部分保持不变

最终编辑

[EL 警告]:2013-09-25 17:14:14.291--ServerSession(1770214826)--异常 [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse。 persistence.exceptions.DatabaseException 内部异常:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:“字段列表”中的未知列“PRODUCTOSVENTASPK” 错误代码:1054 调用:SELECT cantidad, PRODUCTOSVENTASPK, PriceModifiers_idPriceModifier, productos_idProductos, ventas_idventa FROM tiendita.productosventas WHERE (productos_idProductos = ?) bind => [1个参数绑定] 查询:ReadAllQuery(name="productosventasList" referenceClass=Productosventas sql="SELECT cantidad, PRODUCTOSVENTASPK, PriceModifiers_idPriceModifier, productos_idProductos, ventas_idventa FROM tiendita.productosventas WHERE (productos_idProductos = ?)") 构建成功(总时间:3 秒)

public class Productosventas implements Serializable {

    private static final long serialVersionUID = 1L;
    @Column(name = "cantidad")
    private Integer cantidad;
    @JoinColumn(name = "PriceModifiers_idPriceModifier", referencedColumnName = "idPriceModifier")
    @ManyToOne
    private Pricemodifiers priceModifiersidPriceModifier;
    @JoinColumn(name = "productos_idProductos", referencedColumnName = "idProductos", insertable = true, updatable = true)
    @Id
    @ManyToOne(optional = false, cascade = CascadeType.MERGE)
    private Productos productos;
    @JoinColumn(name = "ventas_idventa", referencedColumnName = "idventa", insertable = true, updatable = true)
    @Id
    @ManyToOne(optional = false)
    private Ventas ventas;
    @Transient//transistent worked like a charm
    ProductosventasPK productosventasPK;
...rest of the class }

现在我随心所欲地插入

public static void prueba2() {
    EntityManager em = EclipseLinkUtil.getEntityManagerFactory();
    em.getTransaction().begin();
    try {
        Query query = em.createQuery("from Productos p where p.nombre like 'Lavado de motor' ");
        Productos selledItem = (Productos) query.getSingleResult();
        query = em.createQuery("from Productos p where p.nombre like 'Lavado de ventana' ");
        Productos selledItem2 = (Productos) query.getSingleResult();

    // query = em.createNativeQuery("select curdate() ");
    //java.sql.Date sellingDate = (Date) query.getSingleResult();
        java.util.Date sellingDate = new java.util.Date();

        Ventas v1 = new Ventas();
        v1.setCondicionventaIdcondicionventa(new Condicionventa(1));
        v1.setFecha(sellingDate);

        List<Productosventas> selledItemTableList = new ArrayList<>();
        Productosventas pdv = new Productosventas();
        Productosventas pdv2 = new Productosventas();
        em.persist(v1);

        pdv.setCantidad(2);
        pdv.setProductos(selledItem);
        pdv.setVentas(v1);
        pdv2.setCantidad(2);
        pdv2.setProductos(selledItem2);
        pdv2.setVentas(v1);

        selledItem.getProductosventasList().add(pdv);
        selledItem.getProductosventasList().add(pdv2);

        v1.setProductosventasList(selledItemTableList);


        em.getTransaction().commit();

    } catch (Exception e) {
        em.getTransaction().rollback();
    } finally {
        em.close();
    }
}

【问题讨论】:

  • 尚不清楚解决方案是什么。请编辑您的帖子,在每次编辑后添加信息,描述您所做的更改以及之后哪些内容不起作用

标签: mysql insert eclipselink


【解决方案1】:

要获取要在 Productosventas 中使用的 ID 值,您需要保留引用的实体,然后调用 flush 以让提供程序为它们发出 SQL 插入。只有这样才能在使用身份策略时从数据库中设置 ID,而表排序通常允许预分配,因此它们可以在持久调用中可用。之后,您可以从实体中获取它们并将它们设置在 Productosventas 的嵌入 ID 中。

如果您可以使用 JPA 2.0 功能,另一种方法是使用派生 ID。对于 Productosventas,您需要做的就是使用 @MapsId("productosidProductos") 标记 priceModifiersidPriceModifier,并且提供者在分配 ID 时将使用该关系为您设置嵌入的 ID 字段。对其他关系执行相同的操作,您可以同时持久化所有 3 个实体,ID 值将在所有 3 个实体的刷新或提交之后设置。

http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/mappedbyid

【讨论】:

  • 你好,克里斯,我的 @MapsId 注释有问题(一旦我运行,我得到异常描述:使用 ClassLoader 搜索持久性档案时引发异常:sun.misc.Launcher$AppClassLoader@40f23491)我会喜欢完成这样的事情mkyong.com/hibernate/… 4. 运行它 - 案例 1 用于新类别和新库存。我想你说我可以做类似的事情。看图,stock 是 productos,category 是 ventas,stock_category 是 productosventas
  • 您的错误似乎与 @MapsId 注释本身无关。您在类路径上有正确的 JPA 2.0 persistence.jar 吗? JPA 不允许 pk 有关系,我看不出将关系放在 embeddableid 中的意义;这意味着每次您想要执行简单的查找操作时,您都必须查找引用的实体来构建一个 pk - 该示例甚至抽象了嵌入的 ID,以便实体访问关系,就好像它拥有它一样。仅在实体本身中包含关系并将其标记为 ID 不是更好吗?
  • 是的,我使用 eclipselink 2.1 没有问题,并且 netbeans 向导这意味着我无法控制实体的创建,除非我修改它们,我同意你的观点(embeddableid)为什么要添加和额外的类我只是想要至。您是否介意向我展示“仅在实体本身中拥有关系并将其标记为 ID 不是更好吗?”我对 jpa 很陌生,最重要的是,我遇到的困难比其他新手更难,我真的迷路了,看看我的帖子编辑。问候
  • 我发布的第一个链接显示了一个简单的复合 pk,它使用关系作为 pk 的一部分。如果您遵循该示例,您需要更改的只是删除 productosventasPK 属性,使 ProductosventasPK 成为实体的 PKClass,并更改 ProductosventasPK 以将属性 ventasIdventa 和 productosidProductos 分别重命名为 ventas 和 productos。您还需要使 Productosventas 中的 ventas 和 productos 映射可插入/可更新=true
  • 对不起我的野蛮,但请记住我们即将完成 =) 我尝试了一切,但我得到了这个异常 [EclipseLink-46] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org .eclipse.persistence.exceptions.DescriptorException 请参见第二次编辑 异常描述:应该为主键字段 [tiendita.productosventas.ventas_idventa] 定义一个非只读映射。描述符:RelationalDescriptor(tiendita.entities.Productosventas --> [DatabaseTable(tiendita.productosventas)]) 运行时异常:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多