Issue in JPA Cascade Save with EmbeddedId in child - java

I am having three class. Person,vehicle and a association class to link the person and vehicle
Person
package entity;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
#Entity
#Table(name ="PERSON")
public class Person {
#EmbeddedId
private PKperson pkPerson;
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(cascade=CascadeType.ALL,mappedBy="person")
private Set<PersonVehAssnVO> personVehAssnVOSet=new HashSet<PersonVehAssnVO>();
//getters & setters
}
PKperson
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class PKperson implements Serializable {
#Column(name="NAME", nullable=false)
private String name;
#Column(name="DOB_DT", nullable=false)
private Date dobDt;
}
Vehicle
package entity;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.OneToMany;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
#Entity
#Table(name ="VEHICLE")
public class Vehicle {
#Id
#Column(name="VEHICLE_ID",unique=true, nullable=false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_name")
#SequenceGenerator(allocationSize = 1, name = "seq_name", sequenceName = "SEQ_VEHICLE_ID")
private Long vehicleId;
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(cascade=CascadeType.ALL,mappedBy="vehicle")
private Set<PersonVehAssnVO> personVehAssnVOSet=new HashSet<PersonVehAssnVO>();
private String vehicleName;
//getters & setters
}
Person Vehicle Association
package entity;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
#Entity
#Table(name ="PERSON_VEHICLE_ASSOC")
public class PersonVehAssnVO {
#EmbeddedId
private PKperson pkPerson;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "pkPerson.name",referencedColumnName ="NAME"),
#JoinColumn(name = "pkPerson.dobDt",referencedColumnName ="DOB_DT")})
private Person person;
#ManyToOne
#JoinColumn(name = "VEHICLE_ID", referencedColumnName = "VEHICLE_ID")
private Vehicle vehicle;
//getters & setters
}
//**Save Method**
PKperson pkPerson = new PKperson();
SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = dtFormat.parse("1984-12-14");
pkPerson.setName("Magesh");
pkPerson.setDobDt(date1);
Person person = new Person();
person.setPKperson(pkPerson);
Vehicle vehicle = new Vehicle();
vehicle.setName("Honda350");
PersonVehAssnVO perVehAssnVO = new PersonVehAssnVO();
PersonVehAssnVO.setPKperson(pkPerson);
PersonVehAssnVO.setVehicle(vehicle);
Set<PersonVehAssnVO> assocSet = new HashSet<PersonVehAssnVO>();
assocSet.add(PersonVehAssnVO);
person.setpersonVehAssnVOSet(assocSet);
vehicle.setpersonVehAssnVOSet(assocSet);
Session session = getHibernateTemplate().getSessionFactory().openSession();
transaction = session.beginTransaction();
transaction.begin();
session.save(person);
transaction.commit();
//=============================================================
While Executing the above save logic I am getting error ": [entity.PersonVehAssnVO#component[name,dobDt]{dobDt=magesh, dobDt=1984-12-14 00:00:00}]"
Show Sql Gives "select personVehAssnVO_.NAME, personVehAssnVO_.DOB_DT, personVehAssnVO_.VEHICLE_ID as vehicle_34 from PERSON_VEHICLE_ASSOC where personVehAssnVO_.NAME=? and personVehAssnVO_.DOB_DT=?"
I want to save Person,Vehicle and association in a single save means CASCADE ALL When I save Person.
Any help appreciated

Mark the date in PKPerson with the #Temporal annotation:
#Temporal(TemporalType.TIME)
#Column(name="DOB_DT", nullable=false, length = 8)
private Date dobDt;
According to the Java Doc
This annotation must be specified for persistent fields or properties
of type java.util.Date and java.util.Calendar. It may only be
specified for fields or properties of these types.
The Temporal annotation may be used in conjunction with the Basic
annotation, the Id annotation, or the ElementCollection annotation
(when the element collection value is of such a temporal type.
And according to this SO question:
In plain Java APIs, the temporal precision of time is not defined.
When dealing with temporal data you might want to describe the
expected precision in database. Temporal data can have DATE, TIME, or
TIMESTAMP precision (ie the actual date, only the time, or both). Use
the #Temporal annotation to fine tune that.
I hope this solves your problem. You can interchange the TemporalType with others that match your field type in the database. The column length also can be changed accordingly.
Edit
I think you also need to remove the mappedBy="person" and mappedBy="vehicle" from the annotation of the PersonVehAssnVO sets in the Person and Vehicle classes and replace them with full column properties so that these classes can be the owners of the relationship. Otherwise when you save a person, it will ignore updating any properties marked with the mappedby annotation because this means the Person is not the owner of that relationship.

Related

Is there a #LastAccessedTimestamp in JPA

I want to store the last read time in a Date column when ever someone tries to load or fetch(select query, findBy methods) a entity
I had a look at #PostLoad as explained in this site . Have following questions :-
(a)Just want to know if this is safe to Update entity in #PostLoad
(b) Is there something like #LastAcessedTime in JPA similar to #UpdateTimestamp ?
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.time.LocalDate;
#Data
#Entity
public class SensitiveInfo {
#Id
private Long id;
private String data;
#CreationTimestamp
private LocalDate createdDate;
#UpdateTimestamp
private LocalDate updationTimeStamp;
// Is there a JPA automatic way to Update this field any time hibernate loads this entity ?
private LocalDate updationTimeStamp;
}

Problem while populating child's id with parent's id in Hibernate JPA

i'm not a professional in spring boot / hibernate jpa, so i apologize in advance.
I have 2 Entities, one called Document and the other called Bgo. Document is the parent table and Bgo the child. So my objective is to create the Document and after that, Bgo will receive it's id, for example:
When i create the first Document, it will have id_document = 1, so after that, the Bgo will have id_document = 1 as well.
I want to populate the child's id with the parent's id.
Here is the Parent Entity:
package com.testing.testing.models;
import java.io.Serializable;
import java.sql.Date;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id_document;
private int num_document;
private Date date;
#OneToOne(mappedBy = "document", cascade = CascadeType.ALL)
private Bgo bgo;
public Document() {
}
public Document(Bgo bgo) {
this.id_document = bgo.getId_document();
this.bgo = bgo;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Bgo getBgo() {
return bgo;
}
public void setBgo(Bgo bgo) {
this.bgo = bgo;
}
public long getId_document() {
return id_document;
}
public void setId_document(long id_document) {
this.id_document = id_document;
}
public int getNum_document() {
return num_document;
}
public void setNum_document(int num_document) {
this.num_document = num_document;
}
}
And Child Entity:
package com.testing.testing.models;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
#Entity
#Table(name = "BGO")
public class Bgo implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long id_document;
private String name_bgo;
private int num_bgo;
#OneToOne
#PrimaryKeyJoinColumn(name = "id_document", referencedColumnName = "id_document")
private Document document;
public Bgo() {
}
public Bgo(Document document) {
this.id_document = document.getId_document();
this.document = document;
}
public long getId_document() {
return id_document;
}
public void setId_document(long id_document) {
this.id_document = id_document;
}
public String getName_bgo() {
return name_bgo;
}
public void setName_bgo(String name_bgo) {
this.name_bgo = name_bgo;
}
public int getNum_bgo() {
return num_bgo;
}
public void setNum_bgo(int num_bgo) {
this.num_bgo = num_bgo;
}
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
}
I used the term PrimaryKeyJoinColumn cause i want Bgo's id to be the Document's id, thats why i also used the same name "id_document". So Bgo's id will be Primary and Foreign at the same time (if it is wrong please tell me a better way to do it, knowledge is always welcoming)
I have also Document's Repository:
package com.testing.testing.repository;
import com.testing.testing.models.Document;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DocumentRepository extends JpaRepository<Document, Long> {
}
And Bgo's:
package com.testing.testing.repository;
import com.testing.testing.models.Bgo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BgoRepository extends JpaRepository<Bgo, Long> {
}
Document's Controller:
package com.testing.testing.controllers;
import java.util.List;
import com.testing.testing.models.Document;
import com.testing.testing.repository.DocumentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(value="/document")
public class DocumentController {
#Autowired
DocumentRepository documentRepository;
#GetMapping
public List<Document> listDocument() {
return documentRepository.findAll();
}
#PostMapping
public Document createDocument(#RequestBody Document document) {
return documentRepository.save(document);
}
}
Bgo's Controller:
package com.testing.testing.controllers;
import java.util.List;
import com.testing.testing.models.Bgo;
import com.testing.testing.repository.BgoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(value="/bgo")
public class BgoController {
#Autowired
BgoRepository bgoRepository;
#GetMapping
public List<Bgo> listBgo() {
return bgoRepository.findAll();
}
}
So basically, the problem is this:
enter image description here
When i create a new Document and also the Bgo object, Bgo's id is 0, as you can see in the image, the object Bgo has the "id_document = 0 ", shouldn't it be id_document = 1 ?
And when i try to list Bgo, it still shows id_document = 0:
enter image description here
That's how i want the database to be:
enter image description here
As you can see, they are different tables. But Document has the primary key and is the parent, and Bgo is a child cause it is receiving Document's id. As you can see, Bgo's has the Document's id, it is primary and foreign at the same time, thats why i used PrimaryKeyJoinColumn. Both of them have the same id, Document's id equals Bgo's id. So whenever i create a Document and a Bgo at the same time, both of them should have the same id.
you might need to use the inheritance functionality comes with Spring instead. have a look at this:
https://www.baeldung.com/hibernate-inheritance
you can for instance use the #Inheritance(strategy = InheritanceType.SINGLE_TABLE)
on your parent table. and then you will annotate the child with just the #Entity
and then you will extend it as you normally do in a normal Inheritance scenario
so your parent class will look like so:
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.Table;
import javax.persistence.InheritanceType;
#Entity
#Table(name = "Document")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Document {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private Integer Id;
#Column(name = "num_document")
private int num_document;
#Column(name = "date")
private Date date;
public Document() {
}
public Document( int num_document, Date date) {
super();
this.num_document = num_document;
this.date = date;
}
}
and the child will look like so
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "Bgo")
public class Bgo extends Document {
#Column(name = "name_bgo")
private String name_bgo;
#Column(name = "num_bgo")
private int num_bgo;
public Bgo(String name_bgo, int num_bgo) {
super();
this.name_bgo = name_bgo;
this.num_bgo = num_bgo;
}
public Bgo() {
super();
}
}
and you will have One JPARepository which looks like so;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DocumentRepository extends JpaRepository<Document, Integer> {
}
the result of this code, will generate one table in your database with one extra column dtype which will identify the record to be either Bgo or any other type you might need to add in the future. this is the idea behind inheritance anyway
I hope this helped
Here are the three different inheritance strategy you have using spring
Single mapping is the default mapping
And it uses #inheritance(strategy = InheritanceType.SINGLE_TABLE) annotation to the parent class
In this strategy, the parent class is a table and all its children will be specified in a discriminator column in the parent table. The column called dtype and it contain the name of the entity as a value.
Table per the class strategy is similar to the superclass strategy but the superclass is also an entity you need to avoid this one if you want to make so many join queries
Joined table strategy is used the same as above. In this strategy, the subclasses and the superclass will all be tables in the database, but the subclasses will not inherit the filed of the superclass, it is useful if we want to apply data integrity and null constrains on some field
for more details look here
https://thorben-janssen.com/complete-guide-inheritance-strategies-jpa-hibernate/
choose which one will suit your case and then you can use the implementation I provided in the first answer and you only need to change the this annotation
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)

JPA load entities, but therein in a #OneToMany list, only load specific

Situation:
(using Payara Server)
I have multiple Groups, and each Group has their own specific set of GroupMeetings.
These GroupMeetings are tracked over multiple years.
Each Group contains 100-10000 GroupMeetings.
But usually only the current year's GroupMeetings are queried and used.
Problem:
How can I load all Groups, but only load each Group's GroupMeeting List for a specific interval, for example only the GroupMeetings of 2019? Or, if need be, specific years or ranges, i.e. 2017-2021 etc?
If I simply run a "SELECT *", then with the FetchType.LAZYI will get empty an emtpy List<GroupMeeting>, but as soon as I access it somewhere in the code, all the items will be loaded.
Question:
Whats the best strategy, i.e. somewhat efficient but not overly convoluted?
Is there an easy SQL/JPQL query that I can run with the classes below?
Is there some structural change - especially in the annotations - needed?
Should I consider Criteria API?
Do I have to use two List<GroupMeeting>s, one with the commonly used meetings, the other with the 'old' meetings?
Example:
Here are the two classes:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
#Entity
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings") //
private final List<GroupMeeting> meetings = new ArrayList<>();
}
and
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class GroupMeeting {
#Id //
#GeneratedValue() //
private long id;
private String title;
private Date start;
private Date end;
}
You can use Hibernate filters to achieve that, for instance:
#Entity
#FilterDef(name="groupMeetingFilter",
parameters={#ParamDef( name="fromDate", type="date"), #ParamDef(name="toDate", type="date")} )
public class Group {
#Id //
#GeneratedValue() //
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) #JoinTable(name = "group_meetings")
#Filter(
name = "groupMeetingFilter",
condition="start <= :fromDate and end >= :toDate"
)
private final List<GroupMeeting> meetings = new ArrayList<>();
}
And you need to enable your filter somewhere in your application, just like this:
Session session = HibernateUtil.getSessionFactory().openSession();
Filter filter = session.enableFilter("groupMeetingFilter");
//Define here the dates that you want
filter.setParameter("fromDate", new Date());
filter.setParameter("toDate", new Date());
You could go further with your research and make the filter global available, if you're using Spring for instance, is easier.

Spring Data REST call to `save` receiving object with null variable

I'm continuing the development of a system that uses the React JavaScript library (and related stuff) on the front end and Spring Data REST, Hibernate, PostgreSQL and related stuff on the back end.
This system will be used by people who may own one or more companies and their clients. This means that most/all model objects will have a reference to the Company(ies) that they belong to. Also, company owners will have a few Employees that will have higher level access on this system (or these will be the owners themselves).
I need to implement a functionality where, when a company is inserted in the database, an employee is inserted as well. Also, if one fails, both must fail. Because of how the model was set up, I'm sending an Employee object to be saved, and, within it, the new Company, like this (using Axios):
employee: {
// ...,
company: {
// ....
}
}
Problem is, when the save method is called in the back end, the Company member of the Employee object is null. I've tried a few things, like messing with the relationship, adding an Employee list to the Company object, passing the Company object separately, but nothing worked.
What else could I try? Here are some classes:
Record.java
package xxx.model.common;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;
import lombok.Data;
#Data
#MappedSuperclass
public abstract class Record {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
#NotNull
#Column(name = "deleted")
protected Boolean isDeleted = false;
#NotNull
#Column(name = "enabled")
protected Boolean isEnabled = true;
}
Company.java
package xxx.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import xxx.common.Record;
// ...
import lombok.Data;
import lombok.EqualsAndHashCode;
#Data
#EqualsAndHashCode(callSuper=false)
#Entity
#Table(name="company")
#AttributeOverrides( { #AttributeOverride(name = "id", column = #Column(name = "id_company")) } )
public class Company extends Record {
/*
* ...
*/
// Necessary for Hibernate
protected Company() {}
public Company(/* ... */) {
/*
* ...
*/
}
}
Registry.java
package xxx.model.common;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
#Data
#EqualsAndHashCode(callSuper=false)
#MappedSuperclass
public abstract class Registry extends Record {
#NotBlank
#Column(name = "code", length = 15)
protected String code;
#NotBlank
#Column(name = "name", length = 40)
protected String name;
}
RegistrySingleCompany.java
package xxx.model.common;
import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import com.fasterxml.jackson.annotation.JsonBackReference;
import xxx.model.Company;
import lombok.Data;
import lombok.EqualsAndHashCode;
#Data
#EqualsAndHashCode(callSuper=false)
#MappedSuperclass
public class RegistrySingleCompany extends Registry {
#ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE }, optional= false)
#JoinColumn(name="id_company")
protected Company company;
}
Employee.java
package xxx.model;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import xxx.model.common.RegistrySingleCompany;
import lombok.Data;
import lombok.EqualsAndHashCode;
#Data
#EqualsAndHashCode(callSuper=false)
#Entity
#Table(name="employee")
#AttributeOverrides( { #AttributeOverride(name = "id", column = #Column(name = "id_employee")) } )
public class Employee extends RegistrySingleCompany {
/*
* ...
*/
// Necessary for Hibernate
protected Employee() {}
}
EmployeeRepositoryCustom.java
package xxx.repository.custom;
import org.springframework.data.repository.query.Param;
import xxx.model.Employee;
public interface EmployeeRepositoryCustom {
<S extends Employee> S save(S entity);
}
EmployeeRepositoryCustomImpl.java
package xxx.repository.custom;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import xxx.model.Employee;
public class EmployeeRepositoryCustomImpl implements EmployeeRepositoryCustom {
#Override
#Transactional
public <S extends Employee> S save(#RequestBody S entity) {
/*
* ...
*/
return entity;
}
}
EmployeeProjection.java
package xxx.model.projection;
import org.springframework.data.rest.core.config.Projection;
import xxx.model.Employee;
#Projection(name = "employeeProjection", types = { Employee.class })
public interface EmployeeProjection {
Boolean getIsDeleted();
Boolean getIsEnabled();
String getCode();
String getName();
/*
* ...
*/
}
EmployeeRepository.java
package xxx.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import xxx.model.Employee;
import xxx.model.projection.EmployeeProjection;
import xxx.repository.custom.EmployeeRepositoryCustom;
#RepositoryRestResource(collectionResourceRel = "employee", path = "employees", excerptProjection = EmployeeProjection.class)
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long>, EmployeeRepositoryCustom {}
Thanks in advance.
Edit: added missing classes.
As mentioned before, one of the things I tried was to add an Employee list inside the Company object, which implies using Company's repository instead of the Employee's one to save both objects, but the other object was also arriving null. However, my colleague found out that, by using exported = false inside #RepositoryRestResource(), the value would be received correctly.
That would screw other things up, so we found the following temporary solution:
Create an exported = false repository (EmployeeWrapper) for the sole purpose of delivering the necessary Employee data to construct a new one inside save.
Instead of adding an Employee list inside Company, add an EmployeeWrapper list.
EmployeeWrapper also references Company.
We're still working on a more correct approach.
Update: a more correct approach:
My colleague also found out that, by adding a #Transient Employee list to Company, it's possible to receive the correctly filled out Employee object to save it. I don't know if it works at the repository since, due to other constraints, we moved to use a #RepositoryRestController and are receiving the Company as #RequestBody org.springframework.hateoas.Resource<Company> resource.
We still want to find a better solution, because an Employee list inside Company wasn't planned in our model and, worse yet, we're needing to use list of other things for other methods.
Update: an even better approach:
Experimenting a little more, we created a POJO containing the entities that we needed and received that in the controller, same way as before. Works well.
We're still not satisfied, though. Ideally, we want to receive the Employee to be saved, with the Company to be saved inside it, and save them both at once.

OneToMany relationship without new entity

Using JPA and Hibernate
I have an entity class
#Entity
#Table(name = "ROLES")
public class Role implements Serializable
{
#Column
private List<String> tubes;
// another fields .setters, getters
}
Every String in List tubes - is one row from another table (TUBES).
Table ROLES has an OneToMany relationship with TUBES.
A can make another Entity Tubes and map table TUBES on Entity Tubes. But how I can make this without another entity?
Edit:
I made
#ElementCollection
#CollectionTable(name = "TUBES", joinColumns = #JoinColumn(name = "role_id"))
#Column(name = "tube")
private ArrayList<String> tubes;
Deploy on JBoss. And in runtime I get SQLGrammarException
Query created by JPA is:
/* SELECT r FROM Role r WHERE r.name = ? */ select role0_.AA_ID as AA1_0_, role0_.ROLNAME as ROLNAME0_, role0_.role as PID4_0_ from PIDDB_PID_ROLE role0_ where role0_.ROLNAME=?
17:17:14,661 ERROR [JDBCExceptionReporter] ORA-00904: "ROLE0_"."tube": invalid identifier
You can use #ElementCollection mapping I think this is what are you looking for.
#ElementCollection(fetch=FetchType.LAZY)
#CollectionTable(name="TUBES", joinColumns=#JoinColumn(name="role_id"))
#Column(name="tube")
private List<String> tubes;
Update:
dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
**Update2:**
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

Categories