I want to implement a simple uni-directional one-to-many association. I have tried the below setup. But when I fetch the Tenant entity, I always see null for the subscriptions field.
#Getter
#Setter
#Entity
#ToString
public class Tenant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String tenantKey;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name="tenantKey")
private Set<Subscription> subscriptions;
public Set<Subscription> getSubscriptions() {
return subscriptions;
}
public void setSubscriptions(Set<Subscription> subscriptions) {
this.subscriptions = subscriptions;
}
}
and below is the Subscription entity
#Entity
#Getter
#Setter
#ToString
public class Subscription {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String tenantKey;
private String serviceName;
}
Below is my repository class which I fetch the Tenant object
#ApplicationScoped
public class TenantRepository implements PanacheRepository<Tenant> {
public Uni<Tenant> findByTenantKey(String tenantKey) {
return find("tenantKey= ?1", tenantKey).firstResult();
}
}
Related
I'm a beginner in spring boot, try to make an app with class Department & Employee. I make the relation between these two classes, Department can have many Employee whereas Employee can only have one Department. Every time I ended with an error:
com.learning.model.Employee cannot be converted to java.lang.Integer
Also, I've found two ways to inserting data into DB via API. First through the service layer, 2nd directly through the controller. Thankful if you could advise as to what is the most authentic method among the two above.
Department.java
#Entity
#Table(name = "Department")
#Getter
#Setter
#ToString
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dept_seq")
#SequenceGenerator(initialValue = 1, name = "dept_seq", sequenceName = "dept_sequence")
#Column(name = "id")
private Integer id;
#Column(name = "deptName")
private String deptName;
#OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
#JsonIgnore
private List<Employee> employees;
}
Employee.java
#Entity
#Table(name = "Employee_Dtls")
#ToString
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_seq")
#SequenceGenerator(initialValue = 1, name = "emp_seq", sequenceName = "employee_sequence")
#Column(name = "id")
private Integer id;
#Column(name = "name")
private String name;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "dept_id")
private Department department;
}
DepartmentService.java
#Service
public class DepartmentService {
#Autowired
private EmployeeRepository employeeRepository;
#Autowired
private DepartmentRepository departmentRepository;
//Get Department
public List<Department> getAllDepartments() {
return departmentRepository.findAll();
}
//Add Department
public Department addDepartment(Department department) {
Employee emp = employeeRepository.findById(department.getEmployees().get(department.getId())).orElse(null);
if (null == emp) {
emp = new Employee();
}
emp.setName(department.getEmployees().get(emp.getId()));
department.setEmployees(emp);
return departmentRepository.save(department);
}
}
DepartmentController.java
public class DepartmentController {
#Autowired
private DepartmentService departmentService;
#GetMapping("/get-departments")
public ResponseEntity<List<Department>> getAllDepartments() {
List<Department> departments = departmentService.getAllDepartments();
return new ResponseEntity<>(departments, HttpStatus.OK);
}
#PostMapping("/department")
public ResponseEntity<Department> saveDepartment(#RequestBody Department department) {
Department dept = departmentService.addDepartment(department);
return new ResponseEntity<>(dept, HttpStatus.OK);
}
}
I think you must go over these stacks, these will probably help you to understand how #onetomany annotation works in spring
One to Many Relationship in spring boot REST Api
POSTing oneToMany in a REST call via Spring Boot API
I have 2 entities, connected by many to many. The template should list:
Owner1
shelter1
shelter 2
Owner1
shelter 1
How can I connect the Owner and the Shelter in the controller so that I can pinch into the template
Owner 1- his shelters
Owner 2 - His Shelters
The whole problem is in the controller, what exactly should I pass to the template engine? This is the whole problem, thanks in advance for the answers and time taken
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#DynamicUpdate
#Entity
#Table(name = "owner")
public class Owner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idOwner;
private String name;
private String address;
private String description;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "owner_shelter",
inverseJoinColumns = { #JoinColumn(name = "shelter_id") })
private List<Shelter> shelters = new ArrayList<>();
public void addShelter(Shelter shelter) {
shelters.add(shelter);
shelter.getOwners().add(this);
}
public void removeShelter(Shelter shelter) {
shelters.remove(shelter);
shelter.getOwners().remove(this);
}
}
#Data
#DynamicUpdate
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Entity
#Table(name = "shelter")
public class Shelter {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String address;
private String description;
#ManyToMany(mappedBy = "shelters")
private List<Owner> owners;
public void addOwner(Owner owner) {
owners.add(owner);
owner.getShelters().add(this);
}
public void removeOwner(Owner owner) {
owners.remove(owner);
owner.getShelters().remove(this);
}
}
now i can print only list of shelter or owner
#Autowired
ShelterRepository shelterRepository;
#Autowired
OwnerRepository ownerRepository;
#GetMapping("/shelters")
public String getPage(Authentication authentication, Model model) {
if (authentication != null) {
model.addAttribute("authentication", authentication);
}
List<Shelter> shelters = shelterRepository.findAll();
List<Owner> owners = ownerRepository.findAll();
model.addAttribute("shelters", shelters);
model.addAttribute("owners", owners);
return "shelterList";
}
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'm trying to setup my entity to allow to pks. My database consist of two fields,
dealer_detail_id pk
user_detail_id pk
Both join on id in corresponding tables.
I've tried this thus far without success.
#Embeddable
public class DealerUserPk implements Serializable {
private Integer dealerDetail;
private Integer userDetail;
DealerUser
#Embeddable
#Table(name = "dealer_user", schema = "account")
public class DealerUser implements Serializable {
#EmbeddedId
private DealerUserPk id;
#Id
#ManyToOne
#JoinColumn(name = "dealer_detail_id", referencedColumnName = "id")
private DealerDetail dealerDetail;
#Id
#ManyToOne
#JoinColumn(name = "user_detail_id", referencedColumnName = "id")
private UserDetail userDetail;
DealerDetail
#Entity
#Table(name = "dealer_detail", schema = "account")
public class DealerDetail implements Serializable {
#Id
private Integer id;
UserDetail
#Entity
#Table(name = "user_detail", schema = "account")
public class UserDetail implements Serializable {
#Id
private Integer id;
Can anybody spot what I'm doing wrong?
This is correct:
#Embeddable
public class DealerUserPk implements Serializable {
private Integer dealerDetail;
private Integer userDetail;
But your DealerUser is annotated with embeddable it should be #Entity
as you are using #Table annotation.
Need to add MapsId as it follows
#Entity
#Table(name = "dealer_user", schema = "account")
public class DealerUser implements Serializable {
#EmbeddedId
private DealerUserPk id;
#MapsId("dealerDetail")
#ManyToOne
#JoinColumn(name = "dealer_detail_id", referencedColumnName = "id")
private DealerDetail dealerDetail;
#Id
#MapsId("userDetail")
#JoinColumn(name = "user_detail_id", referencedColumnName = "id")
private UserDetail userDetail;
Try with that.
Try this
#Embeddable
public class DealerUserPk implements Serializable {
#ManyToOne
private DealerDetail dealerDetail;
#ManyToOne
private UserDetail userDetail;
public void setDealerDetail(DealerDetail dealerDetail) {
this.dealerDetail=dealerDetail;
}
public DealerDetail getDealerDetail(){
return this.dealerDetail;
}
public void setUserDetail(UserDetail userDetail) {
this.userDetail=userDetail;
}
public UserDetail getUserDetail() {
return this.userDetail;
}
}
and
#Entity
#Table(name = "dealer_user")
public class ProductItem {
#Id
private DealerUserPk id= new DealerUserPk();
// --- For bidirectional association---
#SuppressWarnings("unused")
#Column(name="dealer_detail_id", nullable=false, updatable=false, insertable=false)
private Integer dealerDetail;
#SuppressWarnings("unused")
#Column(name="user_details_id", nullable=false, updatable=false, insertable=false)
private Integer userDetail;
// ---
public void setDealerDetail(DealerDetail dealerDetail) {
id.setDealerDetail(dealerDetail);
}
public DealerDetail getDealerDetail(){
return id.getDealerDetail();
}
public void setUserDetail(UserDetail userDetail) {
id.setUserDetail(userDetail);
}
public UserDetail getUserDetail() {
return id.getUserDetail();
}
}
Is this possible? Haven't seen much discussion on it.
Sure! It works great from my experience. Here's an example entity:
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PingerEntity {
// ID
#Id
#Getter
#Setter
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// USER
#Getter
#Setter
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private UserEntity user;
// URL
#Getter
#Setter
#Basic(optional = false)
private String url;
/**
* The number of seconds between checks
*/
#Getter
#Setter
#Basic(optional = false)
private int frequency;
#Getter
#Setter
#Basic(optional = false)
#Enumerated(EnumType.STRING)
public MonitorType monitorType;
}
You can use it also with #Data (and it works !)
#Entity
#Data
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
}
I have never tried Lombok with Hibernate but I don't see why it shouldn't work.
Also, take a look here: http://groups.google.com/group/project-lombok/browse_thread/thread/294bd52d9d8695df/7bc6b0f343831af1?lnk=gst&q=hibernate#7bc6b0f343831af1
Also, Lombok project release notes mention Hibernate explicitely.
A simple example; Library.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "libraries")
public class Library {
#Id
#GeneratedValue
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#EqualsAndHashCode.Exclude
// This will be included in the json
private List<Book> books = new ArrayList<>();
#JsonIgnore
public void addBook(Book book) {
books.add(book);
book.setLibrary(this);
}
}
And Book.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "books")
public class Book {
#Id
#GeneratedValue
private Long id;
#NotBlank
private String title;
#ManyToOne
#JoinColumn(name = "library_id") // Owning side of the relationship
#EqualsAndHashCode.Exclude
#JsonIgnore // Avoid infinite loops
private Library library;
}