I have 2 entities, related with #OneToMany.
#Entity
#Table(name = "appeal_templates")
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class AppealTemplate extends AbstractEntity {
private List<Question> questions = new ArrayList<>();
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "template")
public List<Question> getQuestions() {
return questions;
}
}
And second one:
#Setter
#Entity
#Table(name = "appeal_template_questions")
public class Question extends AbstractEntity {
private AppealTemplate template;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "template_id")
public AppealTemplate getTemplate() {
return template;
}
}
AbstractEntity:
#MappedSuperclass
#Setter
#EqualsAndHashCode
#ToString
public abstract class AbstractEntity implements Serializable {
private static final int START_SEQ = 1000;
private Long id;
private LocalDateTime created;
private LocalDateTime updated;
#Id
#SequenceGenerator(name = "global_seq", sequenceName = "global_seq", allocationSize = 1, initialValue = START_SEQ)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "global_seq")
public Long getId() {
return id;
}
#Column(name = "created", updatable = false)
public LocalDateTime getCreated() {
return created;
}
#Column(name = "updated", insertable = false)
public LocalDateTime getUpdated() {
return updated;
}
#PrePersist
public void beforeCreate() {
if (Objects.isNull(created)) {
created = LocalDateTime.now();
}
}
#PreUpdate
public void beforeUpdate() {
if (Objects.isNull(updated)) {
updated = LocalDateTime.now();
}
}
}
I send dto to save like this:
AppealTemplate(id=null, questions=[Question(id=null, initial=false, rank=null, text=Quo vadis?)])
ID not filled while they not sved, both entities saving by AppealTemplate repository, but for Question field template_id not filled.
How to do that template_id filled automatically with first save?
Related
so i am trying to set two related object in each other's fields. But when i debug the code i get that after i set the first object as a field in the other i am getting the following error: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method.
Here is the source code, i hope someone can help. Thank you :D
#Service #Transactional
public class MainService {
#Autowired CustomTableRepository tRepo;
#Autowired UserRepository uRepo;
#Autowired ReservationRepository rRepo;
#SneakyThrows
public void reserveTable(Reservation reservation) {
CustomTable table = tRepo.findById(reservation.getTable().getId()).get();
User user = uRepo.findByUsername(reservation.getUser().getUsername());
Reservation myReservation = new Reservation(null, reservation.getAccepted(), user, table, reservation.getTime());
rRepo.saveAndFlush(myReservation);
if(!(reservationRequirements(rRepo.findByUser(user))))
throw new Exception("something went wrong with the reservation, regarding the requierements");
else {
user.setBalance(user.getBalance() - CONSTANTS.fee );
user.setReservation(myReservation);
myReservation.setAccepted(true);
myReservation.setTable(table);
myReservation.setUser(user);
table.setReservation(myReservation);
table.setAvailable(false);
uRepo.saveAndFlush(user);
tRepo.saveAndFlush(table);
rRepo.save(myReservation);
}
}
/*
* PRIVATE HELPING METHODS
*/
private Boolean reservationRequirements(Reservation reservation) {
User user = uRepo.findByUsername(reservation.getUser().getUsername());
//check if the user has enough money
if(user.getBalance() < CONSTANTS.fee)
return false;
//check if they accepted the money fee.
if(reservation.getAccepted() == false)
return false;
//if the table is occupied
if(reservation.getTable().getAvailable() == null) {
}else {
if(reservation.getTable().getAvailable() == false)
return false;
}
LocalTime time = CONSTANTS.parseLocalTime(reservation.getTime());
if(!(time.isAfter(LocalTime.parse("07:30")) && time.isBefore(LocalTime.parse("22:00"))))
return false;
return true;
}
}
This is how they are all related one to other:
Entity classes:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class CustomTable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Boolean available;
private Boolean busy;
private Boolean arrived;
#OneToOne(mappedBy = "table", cascade = CascadeType.ALL, orphanRemoval = true)
private Reservation reservation;
}
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Reservation {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private Boolean accepted;
#OneToOne
#JoinColumn(name = "user_id")
private User user;
#OneToOne
#JoinColumn(name = "table_id")
private CustomTable table;
private String time;
}
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String type;
}
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String username;
private String password;
private Long number;
private Long balance;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Reservation reservation;
#ManyToMany(fetch = FetchType.EAGER)
private Collection<Role> roles;
}
Thank you a lot for reading.
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 two entities lets call them Categories and Products. These two entities are mapped by a many to many relationship.
My problem is that i am trying to get category information from products. Trying this results in empty categories.
This is my code :
PersistenceEntity
#MappedSuperclass
public class PersistenceEntity implements Serializable {
private static final long serialVersionUID = 4056818895685613967L;
// Instance Variables
#Id
#Column(unique = true)
#GeneratedValue(strategy = GenerationType.TABLE)
protected Long id;
#JsonIgnore
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
protected Date creationDate = new Date();
...Getters and Setters omitted for brevity
}
Category
#Entity
#Table(name = "category")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Category extends PersistenceEntity{
private static final long serialVersionUID = 1L;
#Column(nullable = false)
private String categoryName;
#Column(nullable = false)
private Boolean active;
#Column(nullable = true)
private String picture;
#JsonIgnore
private MetaData metadata;
#ManyToMany(fetch = FetchType.EAGER,mappedBy = "categories")
private Set<Product> products;
...Getters and Setters omitted for brevity
}
Product
#Entity
#Table(name = "products",uniqueConstraints = { #UniqueConstraint(columnNames = "productCode")})
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product extends PersistenceEntity {
private static final long serialVersionUID = 8727166810127029053L;
#Column(name = "product_name")
private String name;
private String productImageUrl;
#JsonIgnore
#ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
#JoinTable(name="category_products",
joinColumns={#JoinColumn(name="product_id", unique = false)},
inverseJoinColumns={#JoinColumn(name="category_id", unique = false)})
private Set<Category> categories;
...Getters and Setters omitted for brevity
}
ProductServiceImplementation
#Service
public class ProductService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Autowired
private ProductRepository productRepository;
public List<Product> getProductsByShopId( Long id) {
List<Product> productList = new ArrayList<>();
productList = productRepository.findByShopId(id);
return productList;
}
public Set<Long> getCategoryIds(List<Product> products){
Set<Long> categoriesIDs = new HashSet<Long>();
for (Product product : products) {
product.getCategories().forEach(category -> {
categoriesIDs.add(category.getId());
});
}
return categoriesIDs;
}
}
The problem is getting the categoryIds that are mapped to the list of products.
How can i get CategoryIds from Product. My getCategoryIds function returns empty always
public Set<Long> getCategoryIds(List<Product> products){
Set<Long> categoriesIDs = new HashSet<Long>();
for (Product product : products) {
product.getCategories().forEach(category -> {
categoriesIDs.add(category.getId());
});
}
return categoriesIDs;
}
I'm trying to make a many to many relationship using EBean in Play2 and I have an issue where EBean trows an error saying my class is not registered.
Heres my mapping classes:
#Entity
public class Booking extends Model {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//... other fields
}
#Entity
public class Store extends Model {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//... other fields
}
#Embeddable
public class ComissionId {
#ManyToOne(targetEntity = Booking.class, optional = false)
#PrimaryKeyJoinColumn(name = "booking_id", referencedColumnName = "id")
private Booking booking;
#ManyToOne(targetEntity = Store.class, optional = false)
#PrimaryKeyJoinColumn(name = "store_id", referencedColumnName = "id")
private Store store;
}
#Entity
#AssociationOverrides({
#AssociationOverride(name = "id.booking", joinColumns = #JoinColumn(name = "booking_id")),
#AssociationOverride(name = "id.store", joinColumns = #JoinColumn(name = "store_id"))
})
public class StoreComission extends Model {
#EmbeddedId
private ComissionId id;
#Column(nullable = false)
private double value;
#Column(nullable = false)
private Date date;
}
The error:
java.lang.RuntimeException:
Error reading annotations for models.ids.ComissionId
Caused by: java.lang.RuntimeException:
Error with association to [class models.Booking] from [models.ids.ComissionId.booking].
Is class models.Booking registered?
In my application.conf I've put ebean.default="models.*" so all this classes should be registered right? (I've tried to move the ComissionId from the package models.ids to models, but the same error ocurred)
You have this error because of #ManyToOne annotations inside your ComissionId class. To make this code work you have to move these relations to StoreComission class. In ComissionId class you should leave only identifiers. In StoreComission class #ManyToOne relation are mapped to the same columns as fields from composite key. But they have attributes 'insertable' and 'updateable' set to false to prevent column duplication.
Here is corrected working code for above scenario:
StoreComission class:
#Entity
public class StoreComission extends Model {
public StoreComission() {
id = new ComissionId();
}
#EmbeddedId
private ComissionId id;
#Column(nullable = false)
public double value;
#Column(nullable = false)
public Date date;
#ManyToOne
#JoinColumn(name = "booking_id", insertable = false, updatable = false)
private Booking booking;
#ManyToOne
#JoinColumn(name = "store_id", insertable = false, updatable = false)
private Store store;
public void setBooking(Booking aBooking) {
booking = aBooking;
id.booking_id = aBooking.id;
}
public Booking getBooking() {
return booking;
}
public void setStore(Store aStore) {
store = aStore;
id.store_id = aStore.id;
}
public Store getStore() {
return store;
}
}
ComissionId class:
#Embeddable
public class ComissionId {
public int booking_id;
public int store_id;
#Override
public int hashCode() {
return booking_id + store_id;
}
#Override
public boolean equals(final Object obj) {
return super.equals(obj);
}
}
I try to gather statistics of visitors for two services. It consists of daily visitors statistics and overall record. Each service can be accessed by different names. For example, user, admin, support etc. Each will have its own record as own statistics.
Here is my DB structure:
service_one: id, name
service_two: id, name
daily_stats: id, date, service_one_id, service_one_visitors,
service_two_id, service_two_visitors, overall_visitors
record_stats: id, service_one_id, service_one_record,
service_one_record_date, service_two_id, service_two_record,
service_two_record_date
Here are the relations between tables:
service_one --- (one to many) ---> daily_stats(service_one_id)
service_one --- (one to many) ---> record_stats(service_one_id)
service_two --- (one to many) ---> daily_stats(service_two_id)
service_two --- (one to many) ---> record_stats(service_two_id)
Mapping for service_one (the same is for service_two). Also setters were omitted in order to shorten the example:
#Entity
#Table(name = "service_one")
public class ServiceOne implements Serializable {
private int id;
private String name;
private Set<RecordStats> recordStats = new HashSet<RecordStats>(0);
private Set<DailyStats> dailyStats = new HashSet<DailyStats>(0);
public ServiceOne() {}
public ServiceOne(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", nullable = false, unique = true)
public int getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<RecordStats> getRecordStats() {
return recordStats;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<DailyStats> getDailyStats() {
return dailyStats;
}
}
daily_stats mapping:
#Entity
#Table(name = "daily_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "date")
})
public class DailyStats implements Serializable{
private int id;
private Date date;
private ServiceOne service_one_id;
private int service_one_visitors;
private ServiceTwo service_two_id;
private int service_two_visitors;
private int overall_visitors;
public DailyStats() {}
public DailyStats(DailyStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#Temporal(DATE)
#Column(name = "date")
public Date getDate() {
return date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_visitors")
public int getService_one_visitors() {
return service_one_visitors;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_visitors")
public int getService_two_visitors() {
return service_two_visitors;
}
#Column(name = "overall_visitors")
public int getOverall_visitors() {
return overall_visitors;
}
}
record_stats mapping:
#Entity
#Table(name = "record_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "service_one_record_date"),
#UniqueConstraint(columnNames = "service_two_record_date")
})
public class RecordStats implements Serializable {
private int id;
private ServiceOne service_one_id;
private int service_one_record;
private Date service_one_rec_date;
private ServiceTwo service_two_id;
private int service_two_record;
private Date service_two_rec_date;
public RecordStats() {}
public RecordStats(RecordStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_record")
public int getService_one_record() {
return service_one_record;
}
#Column(name = "service_one_record_date")
#Temporal(DATE)
public Date getService_one_rec_date() {
return service_one_rec_date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_record")
public int getService_two_record() {
return service_two_record;
}
#Column(name = "service_two_record_date")
#Temporal(DATE)
public Date getService_two_rec_date() {
return service_two_rec_date;
}
}
Trying to create new entry throws exception:
public static void main(String[] args) {
ServiceOne serviceOne = new ServiceOne();
serviceOne.setName("test");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(serviceOne);
session.getTransaction().commit();
//get records
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery("from service_one").list();
for (ServiceOne o : (List<ServiceOne>)result) {
System.out.println(o.getName());
}
session.getTransaction().commit();
session.close();
}
org.hibernate.MappingException: Repeated column in mapping for entity:
VisitorsCounter.model.entity.DailyStats column: id (should be
mapped with insert="false" update="false")
What is wrong with my mapping?
It seems to me that
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
in DailyStats is wrong; you should have name = "service_one_id".
You have the same problem in getService_two_id() and in methods of same names in RecordStats.
May I also ask why don't you name the references in the classes fields serviceOne and serviceTwo instead of service_one_id and service_two_id.