0

I have a problem with persisting new objects to the database. I'm using Eclipselink and Postgresql. When I'm trying to add a new Merchandise, cascade adds also Price object.

Price.java

@Entity
@Table(name = "Prices")
public class Price implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(updatable = false)
private int id;
@Column(updatable = false, nullable = false)
private float value;
@Column(updatable = false, nullable = false)
private Date startDate;
@Column(updatable = false, nullable = true)
private Date endDate;
@ManyToOne(targetEntity=Merchandise.class,cascade=CascadeType.ALL)
@JoinColumn(name="id",nullable = false,updatable = false,insertable=false)
private Merchandise merchandiseId;
@Column(updatable = false, nullable = true)
private float valueBulk;
@Column(updatable = false, nullable = true)
private float valueRetail;
@Column(updatable = false, nullable = true)
private float makeupPercent;
@Column(updatable = false, nullable = true)
private float makeupForce;

Merchandise.java

@Entity
@Table(name="Merchandises")
public class Merchandise implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(updatable = false)
private int id;
@Column(updatable = false)
private int externalId;
@Column(unique = false, nullable = false, updatable = true)
private String name;
@Column(unique = false, nullable = true, updatable = true)
private int available;
@Column(unique = false, nullable = true, updatable = true)
private String description;
@OneToMany(targetEntity = Price.class, mappedBy = "merchandiseId",cascade = CascadeType.PERSIST)
private List<Price> prices;
@OneToMany(targetEntity = MerchandiseCategory.class, mappedBy = "merchandiseId",cascade = CascadeType.PERSIST)
private List<MerchandiseCategory> merchandiseCategories;
@OneToMany(targetEntity = MerchandiseOrder.class, mappedBy = "merchandiseId",cascade=CascadeType.PERSIST)
private List<MerchandiseOrder> merchandiseOrders;
@OneToMany(targetEntity = MerchandiseDiscount.class, mappedBy = "merchandiseId",cascade=CascadeType.PERSIST) //#61
private List<MerchandiseDiscount> discounts; //#61

my code in facede looks like this:

Dao dao = new DAO();//begins transaction etc.
Merchandise m = new Merchandise;
m.set..//setting all needed fields
List<Price> list = new ArrayList<Price>();
Price p = new Price();
p.set..//setting all needed fields
p.setMerchandiseID(m);
list.add(p);
m.setPrices(list);
dao.addMerchandise(m);//persisting

This gets mean error (in Polish base so I'll try to translate it): foreign key restriction violation - Key (id)=(356) is not present in merchandises.

I think this is problem with generating id, id fiels is always replaced by generated id, and i think they are different, but in this case should be the same

tshepang
  • 12,111
  • 21
  • 91
  • 136
sangtraceur
  • 23
  • 2
  • 7
  • If the database is setting the id values, you cannot specify GenerationType.AUTO, you need to pick the one appropriate for your database - possibly IDENTITY. GenerationType.AUTO lets the JPA provider pick its own sequencer for the id, which is then overridden by the database without the provider knowing. This causes problems with foreign keys ans your cache. – Chris Jul 29 '13 at 11:25
  • I tried IDENTITY before, result was the same... – sangtraceur Jul 29 '13 at 12:34
  • You need to match the sequence generator to how the database is assigning the sequence. How is it being assigned? – Chris Jul 29 '13 at 12:35
  • I'm creating a database schema with JPA, I don't really have an SQL code I found fome in this thread http://stackoverflow.com/questions/11825643/configure-jpa-to-let-postgresql-generate-the-primary-key-value but it seems to not work too... – sangtraceur Jul 29 '13 at 13:06

1 Answers1

0

Your Price class uses its "id" field as the as the foreign key to Merchandise. You have also marked the ID attribute mapping to be generated, so it will always be different than what is in Merchandise. Did you intend Price to use its foreign key to Merchandise as the primary key? If so, you need to remove the @GeneratedValue from Price and either 1) need to persist Merchandise first, flush so that its primary key is assigned, and then set the value into p.setId() as well as calling p.setMerchandiseID(m).

or 2) use JPA 2.0's derived ID capability and mark Price's merchandiseId attribute as either @Id (and remove the int id as it isn't needed), or use @MapsId. @Mapsid will allow JPA to set the id value from Merchandise automatically when it is assigned a value. Some info: http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/mappedbyid

If you meant for Price to have its own independent primary key, you need to add a foreign key in the price table:

@ManyToOne(targetEntity=Merchandise.class,cascade=CascadeType.ALL) @JoinColumn(name="fk_merchandiseid",nullable = false) private Merchandise merchandiseId;

Chris
  • 20,138
  • 2
  • 29
  • 43