#OneToMany relationship with #EmbeddedId, giving uninitialized proxy passed to persist() - java

I have googled a lot, but I have not found any solution. Error showed in the log:
org.hibernate.PersistentObjectException: uninitialized proxy passed to persist()
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:99)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:762)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:755)
at org.hibernate.engine.spi.CascadingAction$7.cascade(CascadingAction.java:315)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:399)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:342)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:424)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
Hibernate querys in the log:
(SqlStatementLogger.java:104) - insert into DEST_ALERTAS (EMAIL, ID_DESTINATARIO) values (?, ?)
(SqlStatementLogger.java:104) - update DEST_ALERTAS_SISTEMA set ACTIVO=? where ID_DESTINATARIO=? and ID_SISTEMA=?
I am inserting a new DEST_ALERTAS, so the first insert is ok, and the update is wrong, it should also be a insert.
My code:
DEST_ALERTAS entity
#Entity
#Table(name = "DEST_ALERTAS")
public class DestinatariosAlertasEntidad implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Identificador_DEST_ALERTAS_PK")
#SequenceGenerator(name = "Identificador_DEST_ALERTAS_PK", sequenceName = "SEC_GI_DEST_ALERTAS", allocationSize = 1)
#Column(name = "ID_DESTINATARIO", unique = true, nullable = false)
private int idDestinatario;
#Column(name = "EMAIL", length = 100)
private String email;
#OneToMany(mappedBy = "destinatario", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnore
private Set<DestinatariosAlertasSistemaEntidad> destinatarioSistema = new HashSet<DestinatariosAlertasSistemaEntidad>();
DEST_ALERTAS_SISTEMA entity
#Entity
#Table(name = "DEST_ALERTAS_SISTEMA")
public class DestinatariosAlertasSistemaEntidad implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private DestinatarioSistemaKey clave;
#MapsId("idSistema")
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "ID_SISTEMA", referencedColumnName = "ID_SISTEMA", insertable = false, updatable = false)
private SistemaEntidad sistema;
#MapsId("idDestinatario")
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "ID_DESTINATARIO", referencedColumnName = "ID_DESTINATARIO", insertable = false, updatable = false)
private DestinatariosAlertasEntidad destinatario;
Class used to map the composite key is DestinatarioSistemaKey
#Embeddable
public class DestinatarioSistemaKey implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ID_SISTEMA")
private Integer idSistema;
#Column(name = "ID_DESTINATARIO")
private Integer idDestinatario;
SISTEMAS entity class:
#Entity
#Table(name = "SISTEMAS")
public class SistemaEntidad implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID_SISTEMA", unique = true, nullable = false, precision = 10)
private Integer id;
#OneToMany(mappedBy = "sistema", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<SistemaMotivoEntidad> motivos = new HashSet<SistemaMotivoEntidad>();
#OneToMany(mappedBy = "sistema", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<SistemaCausaEntidad> causas = new HashSet<SistemaCausaEntidad>();
#OneToMany(mappedBy = "sistema", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<SistemaProblemaEntidad> problemas = new HashSet<SistemaProblemaEntidad>();
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "ID_TIPO_SISTEMA")
private TipoSistemaEntidad tipo;
My controller is:
#RequestMapping(value = "/creaDestinatariosAlertas", method = RequestMethod.POST)
public String creaDestinatariosAlertas(
#Validated #ModelAttribute("filtro") FiltroDestinatarioSistemaAlertas usuarioAlerta,
Model model, RedirectAttributes flash, SessionStatus status, HttpServletRequest request, BindingResult result) {
if (result.hasErrors()) {
return VISTA_CREACION_DESTINATARIOS_ALERTAS;
}
DestinatariosAlertasEntidad entidad = new DestinatariosAlertasEntidad();
try {
entidad.setEmail(usuarioAlerta.getEmail());
entidad.setDestinatarioSistema(obtenerListaEntidad(usuarioAlerta.getSistemas(), entidad));
alertasServicio.guardarDestinatario(entidad);
} catch (Exception e) {
logger.error(" Ha fallado a la hora de crear un destinatario. " + e.getMessage() + " - " + e);
}
String mensajeFlash = (entidad.getIdDestinatario() != 0) ? "Destinatario Creado con éxito!"
: "No se ha podido crear el Destinatario.!";
flash.addFlashAttribute(SUCCESS, mensajeFlash);
// Se procede a borrar la sesion.
status.setComplete();
return OK;
}
private Set<DestinatariosAlertasSistemaEntidad> obtenerListaEntidad(List<Integer> lista, DestinatariosAlertasEntidad usuarioAlerta) {
Set<DestinatariosAlertasSistemaEntidad> sistemas = new HashSet<DestinatariosAlertasSistemaEntidad>();
for (Integer sistemaId:lista) {
//Get sistema from DB
SistemaEntidad sistema = this.tablasServicio.buscarSistemaByIdEntidad(sistemaId);
//Composite key creation
DestinatarioSistemaKey key = new DestinatarioSistemaKey();
key.setIdDestinatario(usuarioAlerta.getIdDestinatario());
key.setIdSistema(sistemaId);
DestinatariosAlertasSistemaEntidad entidad = new DestinatariosAlertasSistemaEntidad();
entidad.setClave(key);
entidad.setDestinatario(usuarioAlerta);
entidad.setSistema(sistema);
entidad.setActivo(true);
sistemas.add(entidad);
}
return sistemas;
}
AlertasServicio is an interface for calling RepoClass. What RepoClass does is: this.persist(destinatarioAlertasEntidad);
Any help appreciated.
Sorry for the spanish code!
I have tried deleting cascades on SistemaEntidad , but same result.

Related

Error relationship persistence using Spring Data JPA in a many to one

I have the following code for many to many or many to one relationship persistence using Spring JPA.
This is my repository test https://github.com/Truebu/testJpa.git
This class has three one-to-many relationships, but none work well
#Entity(name = "routine_assignament")
#Table(name = "routine_assignament")
public class RoutineAssignament {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "date_start",nullable = true,columnDefinition = "DATE")
private Date date_start = new Date();
#Column(name = "date_end",nullable = true,columnDefinition = "DATE")
private Date date_end;
#ManyToOne
#JoinColumn(name = "id_user")
private User user;
#ManyToOne
#JoinColumn(name = "id_routine")
private Routine routine;
#OneToMany(mappedBy = "routine_assignament")
private Set<Score> scores = new HashSet<>();
#OneToMany(mappedBy = "routine_assignament")
private Set<Statistic> statistics = new HashSet<>();
#OneToMany(mappedBy = "routine_assignament")
private Set<KeepRoutine> keepRoutines = new HashSet<>();
The other classes
#Entity(name = "score")
#Table(name = "score")
public class Score {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "commentary",nullable = false,columnDefinition = "TEXT", unique = true)
private String commentary;
#Column(name = "assessment",nullable = false,columnDefinition = "INT", unique = true)
private String assessment;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
#Entity(name = "statistic")
#Table(name = "statistic")
public class Statistic {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "time",nullable = false,columnDefinition = "TEXT", unique = true)
private String time;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
and
#Entity(name = "keep_routine")
#Table(name = "keep_routine")
public class KeepRoutine {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
The entity relationship diagram is this:
My mistake is that it doesn't detect these relationships correctly.
When I run it it generates this:
Failed to initialize JPA EntityManagerFactory: mappedBy reference an unknown target entity property: com.example.demo.model.entities.KeepRoutine.routine_assignament in com.example.demo.model.entities.RoutineAssignament.keepRoutines
This error is reproduced with all three classes (KeepRoutine, Statistic and Score), I don't know why
Your OneToMany mapping is not appropriate. You need to use routineAssignament the property name instead of the table name routine_assignament as shown below. This property name is defined in the ManyToOne relationship.
#OneToMany(mappedBy = "routineAssignament")
private Set<Score> scores = new HashSet<>();
#OneToMany(mappedBy = "routineAssignament")
private Set<Statistic> statistics = new HashSet<>();
#OneToMany(mappedBy = "routineAssignament")
private Set<KeepRoutine> keepRoutines = new HashSet<>();

hibernate session save method not working?

I 'm new in spring and hibernate. i have a sample project that not work properly. when i try to save new order from user, i get no error or exceprion, but record not inserted into database.
here my code
strong textStoreController.java
#Autowired
OrderService orderService;
#SuppressWarnings("unchecked")
#RequestMapping(value = "/store/addorder", method = RequestMethod.GET)
public ModelAndView addOrder(HttpSession session) {
ModelAndView model = new ModelAndView();
// create list of products that we have to add in orders
List<CartItem> items = (List<CartItem>) session.getAttribute("cart");
Set<CartItem> itemsSet = new HashSet<CartItem>();
// new order generated and setter methods invoke
Orders order = new Orders(itemsSet);
Date d = new Date();
Date delivery = StoreUtils.deliveryDate(d, 3);
order.setOrderDate(d);
order.setDeliveryDate(delivery);
order.setItems(itemsSet);
for (CartItem cartItem : items) {
itemsSet.add(cartItem);
}
String addOrders = orderService.addOrders(order);
System.err.println("new order add status " + addOrders + "-------------");
// change product quantity after adding new order
if (!addOrders.toLowerCase().contains("error")) {
for (int i = 0; i < items.size(); i++) {
Integer qSale = items.get(i).getQuantity() * (-1);
productService.rechargeProduct(items.get(i).getProduct(), qSale);
}
model.setViewName("successorder");
model.addObject("order", order);
model.addObject("message", addOrders);
session.setAttribute("cart", null);
} else {
session.setAttribute("error", addOrders);
model.setViewName("redirect:/addtocartlist");
}
return model;
}
Orders.java
#Entity
#Table(name = "orders")
public class Orders implements Serializable {
private static final long serialVersionUID = -3672662224925418969L;
#Id
#Column(name = "orderid", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#DateTimeFormat(pattern = "yyyy-mm-dd")
#Column(name = "orderDate", nullable = false)
private Date orderDate;
#DateTimeFormat(pattern = "yyyy-mm-dd")
#Column(name = "delivery", nullable = false)
private Date deliveryDate;
#Column(name = "success", nullable = true, columnDefinition = "tinyint(1) default 0")
private boolean success;
#Column(name = "cancel", nullable = true, columnDefinition = "tinyint(1) default 0")
private boolean canceled;
#Column(name = "cause", nullable = true)
private String cancelCause;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "ORDERS_ITEMS", joinColumns = { #JoinColumn(name = "orderid") }, inverseJoinColumns = {
#JoinColumn(name = "item_id") })
private Set<CartItem> items = new HashSet<CartItem>(0);
//setters and getters
}
CartItem.java
#Entity
#Table(name = "items")
public class CartItem implements Serializable {
private static final long serialVersionUID = 7968604053015663078L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "item_id", nullable = false)
private Long id;
#Column(name = "quantity", nullable = false, columnDefinition = "int(11) default 1")
private Integer quantity;
#Column(name = "totalprice", nullable = false)
private BigDecimal totalprice;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "prd_id", nullable = false)
private Product product;
//setters and getters
}
Product.java
#Entity
#Table(name = "products")
public class Product implements Serializable {
private static final long serialVersionUID = -7738539408628995177L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "prd_id")
private Long id;
#Column(name = "full_name", nullable = false)
private String fullName;
#Column(name = "seller_name")
private String seller;
#Column(name = "company_name", nullable = false)
private String companyName;
#Column(name = "created_date")
#DateTimeFormat(pattern = "yyyy-mm-dd")
private Date createdDate;
#Column(name = "expiry_date")
#DateTimeFormat(pattern = "yyyy-mm-dd")
private Date expiryDate;
#Column(name = "insert_date")
#DateTimeFormat(pattern = "yyyy-mm-dd")
private Date insertDate;
#Column(name = "likes", nullable = true)
private Integer likeCount;
#Column(name = "quantity", nullable = true)
private Integer quantity;
#Column(name = "price", nullable = false)
private BigDecimal price;
#Column(name = "category", nullable = false)
private String category;
#Column(name = "description", nullable = true)
private String description;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "product")
private Set<CartItem> items;
//setters and getters
}
and finally here is my doa implementation code
OrdersDaoImpl.java
#Repository("ordersDao")
public class OrdersDaoImpl implements OrdersDao {
#Autowired
SessionFactory sessionFactory;
protected Session session() {
try {
return sessionFactory.getCurrentSession();
} catch (HibernateException e) {
return sessionFactory.openSession();
}
}
public String addOrders(Orders orders) {
String result = "";
try {
session().save(orders);
result = "success";
} catch (Exception e) {
if (e.getMessage().toLowerCase().contains("duplicate"))
result = "error this order already was exist";
else
result = "error " + e.getMessage();
System.err.println(result);
} finally {
session().clear();
}
return result;
}
}
when i try to add new order i get no exception. why my service not work?
i have another controller in my project, that manage users. in that controller and dao implementation add and remove user working properly.
i think i have logic error in my code for one to many and many to many. please help me to overcome this fail.

JPA: Use a multiple One-to-many relationships with composite keys

I have these entities:
Run entity:
#Entity
#Table(name = "run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "runId")
public class Run implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "run_id")
private Long runId;
#Column(name = "status")
private Integer status;
#Column(name = "create_date")
private Date date;
#Column(name = "config_id")
private Long configId;
#Column(name = "stream_id")
private Long streamId;
#OneToOne(mappedBy = "run", cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "run_id", unique = true, nullable = true, insertable = true, updatable = true)
private StreamRun streamRun;
...
}
and StreamRun entity:
#Entity
#Table(name = "stream_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "streamId")
public class StreamRun implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long streamId;
#Column(name = "run_id", insertable = false, updatable = false)
private Long runId;
#Column(name = "stream_name")
private String streamName;
#OneToOne
#JoinColumn(name = "run_id")
private Run run;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "stream", orphanRemoval = true, targetEntity = JobRun.class)
private List<JobRun> jobs = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "streamRun", orphanRemoval = true, targetEntity = StreamEvent.class)
private List<StreamEvent> events = new ArrayList<>();
....
}
and JobRun entity:
#Entity
#Table(name = "jobs_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
#IdClass(JobRunKey.class)
public class JobRun implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Id
#Column(name = "run_id", insertable = false, updatable = false)
private Long runId;
#Column(name = "name")
private String name;
#Column(name = "type")
private String jobType;
#Column(name = "script")
private String script;
#Column(name = "status")
private Integer status;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "run_id", referencedColumnName = "run_id"), #JoinColumn(name = "job_stream_id", referencedColumnName = "id") })
private StreamRun stream;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class)
public List<JobDependencyRun> dependencies = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class)
public List<JobEvent> events = new ArrayList<>();
....
}
And all the columns are defined in the MySQL database, Table job_run have composite key of (id and run_id).
The problem is in JobRun entity:
If I define "run_id" field as #ID then an exception appear (when insert)
Parameter index out of range (8 > number of parameters, which is 7).
If I define it without #ID then an exception appear (when update)
Duplicate entry '4-78' for key 'PRIMARY'
If I remove the whole field definition from entity since it is foreign key then the exception will be:
Unable to find column with logical name run_id
"Although the column exists in the table".
Please, can anyone help me?
Do I do anything wrong in the code?
I have managed to find a solution, by modifying JobRun entity as below, and change\access the value of runId from direct setter and getter method.
#Entity
#Table(name = "jobs_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
#IdClass(JobRunKey.class)
public class JobRun implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Id
#Column(name = "run_id")
private Long runId;
#Column(name = "job_stream_id")
private Long streamId;
#Column(name = "name")
private String name;
#Column(name = "type")
private String jobType;
#Column(name = "script")
private String script;
#Column(name = "status")
private Integer status;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "run_id", referencedColumnName = "run_id", insertable = false, updatable = false),
#JoinColumn(name = "job_stream_id", referencedColumnName = "id", insertable = false, updatable = false) })
private StreamRun stream;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class)
public List<JobDependencyRun> dependencies = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class)
public List<JobEvent> events = new ArrayList<>();
...
}

Persisting 2 table with the same generated id

I try to persist one parent entity which is joined with another child entity, but the problem is that the id is not generated for this child when persisting so I have this error : [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] ORA-01400: cannot insert NULL into ("L2S$OWNER"."SABRI"."TRANSITION_MATRIX_ID")
there is the child Entity :
#Data
#Entity
#IdClass(MyLibrarySabriEntityPK.class)
#Table(name = "SABRI", schema = "L2S$OWNER", catalog = "")
public class MyLibrarySabriEntity extends ActionForm {
#Access(AccessType.FIELD)
#Id
#ManyToOne
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
#Id
private String RATING_ID_ROW;
#Id
private String RATING_ID_COL;
#Basic
#Column(name = "TRANSITION_PROBABILITY", nullable = true, insertable = true, updatable = true, precision = 20)
private Double TRANSITION_PROBABILITY;}
the PK class :
#Data
public class MyLibrarySabriEntityPK implements Serializable {
private String TRANSITION_MATRIX_ID;
private String RATING_ID_ROW;
private String RATING_ID_COL;
public MyLibrarySabriEntityPK(String TRANSITION_MATRIX_ID,String RATING_ID_COL,String RATING_ID_ROW ){
this.TRANSITION_MATRIX_ID=TRANSITION_MATRIX_ID;
this.RATING_ID_COL = RATING_ID_COL;
this.RATING_ID_ROW= RATING_ID_ROW;
}
}
there is the parent Entity:
#Data
#Entity
#Table(name = "TEST", schema = "L2S$OWNER", catalog = "")
public class MyLibraryTestEntity extends ActionForm {
#Access(AccessType.FIELD)
#OneToMany(mappedBy = "sabriEntity", cascade = CascadeType.PERSIST)
private final List<MyLibrarySabriEntity> entities = new ArrayList<MyLibrarySabriEntity>(25);
public void addEntitysabri(MyLibrarySabriEntity entity) {
getEntities().add(entity);
entity.setSabriEntity(this);
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "IdGenerated")
#GenericGenerator(name = "IdGenerated", strategy = "dao.Identifier")
#Column(name = "ID_TRANSITION_MATRIX", nullable = false, insertable = false, updatable = false, length = 10)
private String ID_TRANSITION_MATRIX;
#Basic
#Column(name = "REFERENCE", nullable = true, insertable = true, updatable = true, precision = 0)
private Integer reference;}
And here I try to persist the parent table which is supposed to persist also the child table but the Id is not generated !
MyLibrarySabriEntity Entity = null;
MyLibraryTestEntity test = getMyLibraryTestEntity(matrixStartDate, matrixName); // here I get the values of my entity test (parent)
try {
transaction.begin();
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 20; col++) {
double val = cells.get(row + FIRST_ROW, col + FIRST_COL).getDoubleValue();
Entity = getMyLibrarySabriEntity(col, row, val); // this get the values of the Entity parameters (child)
Entity.setSabriEntity(test);
test.addEntitysabri(Entity);
em.persist(test);
}
}
} catch (Exception e) {
if (transaction.isActive())
transaction.rollback();
LOGGER.warn(e.getMessage(), e);
} finally {
if (transaction.isActive())
transaction.commit();
em.close();
}
Assuming you are using JPA 2.0+
Remove this mapping completely:
#Id
#Column(name = "TRANSITION_MATRIX_ID", nullable = false,
insertable = true, updatable = true, length = 100)
private String TRANSITION_MATRIX_ID;
and put the #Id directly on the ManyToOne and remove the insertable and updateable attributes.
#Access(AccessType.FIELD)
#Id
#ManyToOne
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
Update your ID class accordingly. Any previous reference to TRANSITION_MATRIX_ID should be replaced with a reference to sabriEntity. You are also confusing #EmbeddedId and #IdClass: Only the former would contain column definitions whereas you are using the latter approach.
public class MyLibrarySabriEntityPK implements Serializable {
private String sabriEntity;
private String RATING_ID_ROW;
private String RATING_ID_COL;
}
See:
https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#JPA_2.0
Thank's to Alan Hay, I found the problem , I change the property TRANSITION_MATRIX_ID of my IDclass to sabriEntity and I delete all the annotation of this class !
Child entity
#Data
#Entity
#IdClass(MyLibrarySabriEntityPK.class)
#Table(name = "SABRI", schema = "L2S$OWNER", catalog = "")
public class MyLibrarySabriEntity extends ActionForm {
#Access(AccessType.FIELD)
#ManyToOne
#Id
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
#Id
private String RATING_ID_ROW;
#Id
private String RATING_ID_COL;
#Basic
#Column(name = "TRANSITION_PROBABILITY", nullable = true, insertable = true, updatable = true, precision = 20)
private Double TRANSITION_PROBABILITY;
Parent Entity
#Data
#Entity
#Table(name = "TEST", schema = "L2S$OWNER", catalog = "")
public class MyLibraryTestEntity extends ActionForm {
#Access(AccessType.FIELD)
#OneToMany(mappedBy = "sabriEntity", cascade = CascadeType.PERSIST)
private final List<MyLibrarySabriEntity> entities = new ArrayList<MyLibrarySabriEntity>(25);
public void addEntitysabri(MyLibrarySabriEntity entity) {
getEntities().add(entity);
entity.setSabriEntity(this);
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "IdGenerated")
#GenericGenerator(name = "IdGenerated", strategy = "dao.Identifier")
#Column(name = "ID_TRANSITION_MATRIX", nullable = false, insertable = false, updatable = false, length = 10)
private String ID_TRANSITION_MATRIX;
#Basic
#Column(name = "REFERENCE", nullable = true, insertable = true, updatable = true, precision = 0)
private Integer reference;
PK Class
#Data
public class MyLibrarySabriEntityPK implements Serializable {
private MyLibraryTestEntity sabriEntity;
private String RATING_ID_ROW;
private String RATING_ID_COL;
public MyLibrarySabriEntityPK() {
}
public MyLibrarySabriEntityPK(MyLibraryTestEntity sabriEntity,String RATING_ID_COL,String RATING_ID_ROW ){
this.sabriEntity=sabriEntity;
this.RATING_ID_COL = RATING_ID_COL;
this.RATING_ID_ROW= RATING_ID_ROW;
}
}

Mapping many-to-many relation and Embeddable class with jpa

I'm using EJB 3 and JPA 2 in my application, i have 2 entities with many to relationship and want to persist them but fortunately after hours of searshing and trying i can't do it, so this is my code:
#Entity
public class Destinataire implements Serializable {
#Id
#Basic(optional = false)
#Size(min = 1, max = 50)
#Column(name = "ADRESSE")
private String adresse;
#OneToMany(mappedBy = "destinataire")
private Set<Envois> envoisSet;
//getters and setters
}
#Entity
public class Envois implements Serializable {
#EmbeddedId
protected EnvoisPK envoisPK = new EnvoisPK();
#Size(max = 4)
#Column(name = "TYPENVOIS")
private String typenvois;
#JoinColumn(name = "IDMAIL", referencedColumnName = "IDMAIL", insertable = false, updatable = false)
#ManyToOne(optional = false)
private MailAEnvoyer mailAEnvoyer;
#JoinColumn(name = "ADRESSE", referencedColumnName = "ADRESSE", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Destinataire destinataire;
}
#Embeddable
public class EnvoisPK implements Serializable {
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "ADRESSE")
private String adresse;
#Basic(optional = false)
#NotNull
#Column(name = "IDMAIL")
private BigDecimal idmail;
}
#Entity
#Table(name = "MAILAENVOYER")
public class MailAEnvoyer implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "IDMAIL")
private BigDecimal idmail;
#JoinTable(name = "ENVOIS", joinColumns = {
#JoinColumn(name = "IDMAIL", referencedColumnName = "IDMAIL")}, inverseJoinColumns = {
#JoinColumn(name = "ADRESSE", referencedColumnName = "ADRESSE")})
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private Set<Destinataire> destinataireSet;
#OneToMany(mappedBy = "mailAEnvoyer", cascade = CascadeType.ALL)
private Set<Envois> envoisSet;
}
this is how i'm proceed :
Envois e = new Envois("CCI");
Destinataire dest = new Destinataire("adress");
destinataireService.create(dest);
e.setDestinataire(dest);
currentMailAEnvoyer.getEnvoisSet().add(e);
mailService.save(currentMailAEnvoyer);
but always i get an exception that EnvoisPK have adresse and idmail null,
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("MAILING"."ENVOIS"."IDMAIL")
Error Code: 1400
Call: INSERT INTO ENVOIS (TYPENVOIS, IDMAIL, ADRESSE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(entities.Envois[ envoisPK=entities.EnvoisPK[ adresse=null, idmail=null ] ])
you can add in the entity MailAEnvoyer the method below:
#PostPersist
public void postPersist() {
for (Envois e : envoisSet) {
e.getEnvoisPK().setIdmail(this.getIdmail());
}
}

Categories