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;
}
Related
I have a ValuedCustomer and Order and I want to do a bidirectional relationship in hibernate. How do I do this? Thanks
#Entity
#Table(name="VCUST")
#DiscriminatorValue("VCUST")
#PrimaryKeyJoinColumns({
#PrimaryKeyJoinColumn(name="CUST_ID",referencedColumnName="ID"),
#PrimaryKeyJoinColumn(name="CUST_TYPE",referencedColumnName="TYPE")
})
public class ValuedCustomer extends Customer {
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL,orphanRemoval = true)
#JoinColumn(name = "customer_order", nullable = true)
private Set<Order> orders = new HashSet<>();
}
#Entity
#Table(name=“Order”)
public class Order {
#Id
private int id;
}
That's easy. Important is the mappedBy attribute in #OneToMany that indicates that the realtionship is managed by the Order entity.
#Entity
#Table(name="VCUST")
#DiscriminatorValue("VCUST")
#PrimaryKeyJoinColumns({
#PrimaryKeyJoinColumn(name="CUST_ID",referencedColumnName="ID"),
#PrimaryKeyJoinColumn(name="CUST_TYPE",referencedColumnName="TYPE")
})
public class ValuedCustomer extends Customer {
#OneToMany(mappedBy= 'valuedCustomer" fetch = FetchType.LAZY, cascade = CascadeType.ALL,orphanRemoval = true)
private Set<Order> orders = new HashSet<>();
}
#Entity
#Table(name=“Order”)
public class Order {
#Id
private int id;
#ManyToOne
private ValuedCustomer valuedCustomer;
}
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 base mapping class which contains some common fields
#MappedSuperclass
#Data
public class NodeElement {
#Id
private String id;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private ElementPosition elementPosition;
}
And i have few classes which extends from this NodeElement class
#Data
#Entity(name = "node")
#Table(name = "NODE")
public class Node extends NodeElement {
#ManyToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "PARENT_NODE_ID")
private Node parentNode;
#Column(name = "MESSAGE")
private String message;
#Column(name = "TITLE")
private String title;
#OneToMany(mappedBy = "node", cascade = CascadeType.ALL, orphanRemoval = true)
private List<NodeButton> nodeButtons;
#OneToMany(mappedBy = "node", cascade = CascadeType.ALL, orphanRemoval = true)
private List<NodeAsset> nodeAssets;
}
For CRUD operations i'm using spring-data repository:
public interface NodeElementRepository extends CrudRepository<NodeElement, String> {
}
And it's working perfectly fine for saving entities:
NodeElement nodeModel = elementConverter.convert(nodeElement);
this.nodeElementRepository.save(nodeModel);
But when i try to find entity by Id
Optional<NodeElement> node = this.nodeElementRepository.findById(nodeModel.getId());
i get following error:
org.hibernate.UnknownEntityTypeException: Unable to locate persister: by.com.lifetech.lifeEmployeeBot.model.NodeElement
Is it possible to get entity by using base repository? Or do i have to use specific one(NodeRepository instead of NodeElementRepository)?
I changed mapping of my NodeElement class:
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Entity
#Data
public class NodeElement {
#Id
private String id;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private ElementPosition elementPosition;
}
And after that i'm able to get entity by id by using NodeElementRepository class
Try to change String for Long in
public interface NodeElementRepository extends CrudRepository
If that doesnt work try to write Repository that extending JpaRepository
#Repository //remember about this!
public interface NodeElementRepository extends JpaRepository<NodeElement, Long> {
}
Also try method
.findOne(id)
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"
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.