I am trying to make a OneToMany relationship between User and Project but I am getting following error:
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: ProjectDTO.FKUser in UserDTO.projectDTOs
My User class look like below
#Entity
#Table(name = "USER")
public class UserDTO implements java.io.Serializable {
private Integer iduser;
private Set<ProjectDTO> projects = new HashSet<ProjectDTO>(0);;
public UserDTO() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "IDUser", unique = true, nullable = false)
public Integer getIduser() {
return this.iduser;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "FKUser")
public Set<ProjectDTO> getProjectDTOs() {
return projects;
}
}
And my Project class looks like
#Entity
#Table(name = "Project")
public class ProjectDTO implements java.io.Serializable {
private Integer idproject;
private UserDTO FKUser;
public ProjectDTO() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "IDProject", unique = true, nullable = false)
public Integer getIdproject() {
return this.idproject;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "FKUser", referencedColumnName = "IDUser")
public UserDTO getUserDTO() {
return FKUser;
}
}
I went through some similar questions but I was unable to figure out where I was going wrong. Maybe I am missing something very obvious.
Thanks a lot
In mappedBy you must use field name (or part of the getter name without get for property-based access), not column name.
//...
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userDTO")
public Set<ProjectDTO> getProjectDTOs() {
return projects;
}
//...
Note: also need to add setters.
mappedBy needs to point to the entity that does the mapping, so I believe it should be mappedBy="USER"
Related
I have EcranChamp entity
#Entity
#IdClass(EcranChampId.class)
public class EcranChamp {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ecran")
Ecran ecran;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "champ")
Champ champ;
...
And EcranChampId
#Embeddable
public class EcranChampId implements Serializable {
private Champ champ;
private Ecran ecran;
...
Every time i am trying to save an EcranChamp element i have this following error
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to convert request element: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found
Try something like this:
#Entity
#Table(name = "<entity name>")
public class EcranChamp {
#EmbeddedId
#AttributeOverrides({ #AttributeOverride(name = "id_ecran", column = #Column(name =
"<column name>", nullable = false)),
#AttributeOverride(name = "id_champ", column = #Column(name = "<column name>", nullable = false)) })
EcranChampId id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_ecran")
Ecran ecran;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_champ")
Champ champ;
//getters & setters
}
#Embeddable
public class EcranChampId implements Serializable {
#Column(name = "id_champ", nullable = false)
private Long id_champ;
#Column(name = "id_ecran", nullable = false)
private Long id_ecran;
//getters & setters
}
You shoud use #EmbeddedId annotation.
Please, change your EcranChampId class to this:
#Embeddable
public class EcranChampId implements Serializable {
#ManyToOne
private Champ champ;
#ManyToOne
private Ecran ecran;
//getters and setters
}
And change your EcranChamp class to this:
#Entity
#Table(name = "champ_has_ecran_table_name")
#AssociationOverrides({
#AssociationOverride(name = "pk.champ", joinColumns = #JoinColumn(name = "champ_id"))
#AssociationOverride(name = "pk.ecran", joinColumns = #JoinColumn(name = "ecran_id"))
})
public class EcranChamp {
#EmbeddedId
private EcranChampId pk;
public EcranChamp() {
pk = new EcranChampId();
}
public EcranChampId getPk() {
return pk;
}
public void setPk(EcranChampId pk) {
this.pk = pk;
}
#Transient
public Champ getChamp() {
return pk.getChamp();
}
public void setChamp(Champ champ) {
pk.setChamp(champ);
}
#Transient
public Ecran getEcran() {
return pk.getEcran();
}
public void setChamp(Ecran ecran) {
pk.setEcran(ecran);
}
}
And use it like this:
public class Champ {
#OneToMany(mappedBy = "pk.champ")
private Collection<EcranChamp> ecranChamps;
//getters and setters
}
Also, if EcranChamp or EcranChampId has no other fields i will recommend you to use #ManyToMany annotation instead EcranChamp class like this:
public class Champ {
#ManyToMany
#JoinTable(
name = "champ_has_ecran_table_name",
joinColumns = #JoinColumn(name = "champ_id", referencedColumnName = "id", nullable = false),
inverseJoinColumns = #JoinColumn(name = "ecran_id", referencedColumnName = "id", nullable = false)
)
private Collection<Ecran> ecrans;
//getters and setters
}
I have a problem with retrieving an entity using the child's entity as a search parameter. Entities are related to many to one relationship as unidirectional and each object is fetched as FetchType.LAZY.
When I looking for an entity by a child entity, the result is null. But when I set to fetch as Eager it is correct.
My Entities:
#NoArgsConstructor
#Getter
#Entity
#Table(name = "partner")
public class PartnerEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String login;
public PartnerEntity(String login) {
this.login = login;
}
}
#NoArgsConstructor
#Getter
#Entity
#Table(name = "point")
public class PointEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "partner_Id")
private PartnerEntity partnerEntity;
public PointEntity(PartnerEntity partnerEntity) {
this.partnerEntity = partnerEntity;
}
}
#NoArgsConstructor
#Getter
#Entity
#Table(name = "orer")
public class OrdEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PAYMENT_POINT_ID")
private PointEntity pointEntity;
public OrdEntity(PointEntity pointEntity) {
this.pointEntity = pointEntity;
}
}
#NoArgsConstructor
#ToString
#Getter
#Entity
#Table(name = "BL")
public class BLEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PARTNER_LOGIN", referencedColumnName = "login")
private PartnerEntity partnerEntity;
private String number;
public BLEntity(PartnerEntity partnerEntity, String number) {
this.partnerEntity = partnerEntity;
this.number = number;
}
}
And I looking for BLEntity using OrdEntity child:
final OrdEntity byId = ordRepo.findById(id);
final PartnerEntity partnerEntity = order.getPointEntity().getPartnerEntity();
final BLEntity blEntityResult= blRepo.findOneByNumberAndPartner(number, partnerEntity);
The object partnerEntity is not null, it is correct object.
I got blEntityResult as null but if I change in PointEntity fetch to FetchType.EAGER, blEntityResult is not null(correct).
My custom query in repository below:
public interface BLRepo extends JpaRepository<BLEntity, Long> {
#Query("select b from BLEntity b where b.number = :number and b.partnerEntity= :partner")
BLEntity findOneByNumberAndPartner(#Param("number") String number, #Param("partner") PartnerEntity partner);
}
why does happens, if the partner object being downloaded is not null and is correct?
I think you should add the mapping in both sides,
because of default fetch type for #AllToMany=Lazy and #ManyToAll = Eager.
just add below code inside PartnerEntity.
#OneToMany(mappedBy="partnerEntity" , fetch = FetchType.Eager )
List<BLEntity> blEntity = new ArrayList<>();
I change FetchType into Eager in PointEntity:
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "partner_Id")
private PartnerEntity partnerEntity;
And everything is ok, but I don't understand why it does not work with PaymentType.Lazy. When I am looking for:
final PartnerEntity partnerEntity = order.getPointEntity().getPartnerEntity();
I get correct entity "PartnerEntity" which has proper login's field (login'field has value "test").
When I turned logged level to 'TRACE' I saw, Hibernate not binding correct login's parameter, it set null instead "test") why? :)
I have a User Class
#Entity(name = "users")
#Table(name = "users")
public class User implements UserDetails {
static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id", nullable = false)
private Long id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "password", nullable = false)
private String password;
}
Tied to a simple Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
And I have an Instructor Class that has a nested User object
#Entity
#Table(name = "instructors")
public class Instructor {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "instructor_id", nullable = false, updatable = false)
private Long id;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "course_id")
private List<Course> courses;
}
It is saved with the following repository
public interface InstructorRepository extends PagingAndSortingRepository<Instructor, Long> {
}
The JSON I am posting
{
"user": {
"id": 1
}
}
When I try to do a POST to /instructors . User is coming in null. Is there something I am missing to get JPA to tie the two together? I have tried adding CascadeType.ALL onto the field and that only throws a detached persist exception.
Leave the CascadeType.ALL to Instructor like you already tried:
#ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
#JoinColumn(name = "user_id")
private User user;
In addition add the following to User. Seems to work with me. It provides the mapping information and makes JPA treat User managed
#OneToMany(mappedBy="user")//, cascade=CascadeType.ALL)
private List<Instructor> instructors = new ArrayList<>();
I have commented out the cascadeType in the above but it might be useful if you want to persist User wit all of its Instructors.
I'm having trouble persists the following entities:
#Entity
#Table(name="entityOne")
public class EntityOne implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id;
#OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne")
private List<EntityTwo> entities;
}
#Entity
#Table(name="entityTwo")
public class EntityTwo implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id;
#Inject
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="entityOne", referencedColumnName="id")
private EntityOne entityOne;
}
In EntityOneDAO:
em.merge(entityOne);
And it is only persisted to EntityOne and not the list of EntityTwo ... How do I persist the list ?
Thanks all
You need to take care of both:
transitive persistence (using Cascade)
synchronizing both end of the bi-directional association.
So EntityOne should Cascade Persist and Merge to EntityTwo:
#OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne", cascade = { CascadeType.PERSIST, CascadeType.MERGE})
private List<EntityTwo> entities = new ArrayList<>();
As you can see, you should always initialize your collection classes to avoid unnecessary null checks.
And it's always better to add the following helper child adding utility in your parent classes (e.g. EntityOne)
public void addChild(EntityTwo child) {
if(child != null) {
entities.add(child);
child.setEntityOne(this);
}
}
Then you can simply call:
EntityOne entityOne = new EntityOne();
entityOne.setProperty("Some Value");
EntityTwo entityTwo_1 = new EntityTwo();
entityTwo_1.setName("Something");
EntityTwo entityTwo_2 = new EntityTwo();
entityTwo_2.setName("Something");
entityOne.addChild(entityTwo_1);
entityOne.addChild(entityTwo_2);
entityManager.persist(entityOne);
P.S.
Please remove the #Inject annotation from the EntityTwo class. Entities are not Components.
And persist is much more efficient than merge, when you want to insert new entities.
You should explicitly set each entityTwo objects' entityOne field.
Such that:
entityTwo_1.setEntityOne(entityOne);
entityTwo_2.setEntityOne(entityOne);
entityOne.entities.add(entityTwo_1);
entityOne.entities.add(entityTwo_2);
em.merge(entityOne);
Try this:
public class EntityOne implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id;
#OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne",
cascade = { CascadeType.ALL})
private List<EntityTwo> entities;
}
#Entity
#Table(name="entityTwo")
public class EntityTwo implements Serializable {
#Id
#Column(name = "id", nullable = false)
private Integer id;
#Inject
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="entityOne", referencedColumnName="id")
private EntityOne entityOne;
}
You can read here, about the CascadeType.
edited.
I have a Java class with Hibernate annotations that refers to another POJO:
#Entity
#Table(name = "Patient_Visit_Transaction")
public class PatientVisitTransaction extends Bean {
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "transaction_id")
List<TransactionNoteDW> notes;
....
}
The other class is this:
#Entity
#Table(name = "Transaction_note_dw")
public class TransactionNoteDW extends DateAuditableBean {
#Id
#Column(name = "note_seq")
private long id;
#Column(name = "transaction_id")
private String transactionId;
}
I am trying to delete a PatientVisitTransaction and I get an error:
mappedBy reference an unknown target entity property: TransactionNoteDW.transaction_id in PatientVisitTransaction.notes.
I guess it is trying to map the notes to transaction_id. How do I specify the correct mapping or am I completely off on my assessment?
I think you might want to map like this:
public class TransactionNoteDW extends DateAuditableBean {
//....
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "patient_id")
private PatientVisitTransaction patient;
}
public class PatientVisitTransaction extends Bean {
//....
#OneToMany(fetch = FetchType.LAZY, mappedBy = "patient")
List<TransactionNoteDW> notes;
}