Lets say I have bidirectional one-to-many association between Parent-Child, mapped as follows:
TradingAccount.java
public class TradingAccount {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "tradingAccount", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UnderlyingPerTradingAccount> underlyingPerTradingAccounts;
#Version
private Long version;
}
UnderlyingPerTradingAccount.java
public class UnderlyingPerTradingAccount {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(cascade = {CascadeType.PERSIST})
private TradingAccount tradingAccount;
private Boolean enableBuy;
private Boolean enableSell;
}
this code work, but the problem after saving or updating Trading Account I found new three trading account in the database (primary key + null in all other columns)
Related
I work with an embedded H2 database in which I use the #OneToMany relationship to relate an entity instance (product) to multiple instances of the other entities (suppliers); it's useful when I have specific suppliers for a particular product.
However now, I want to associate all the suppliers with every single product; I don't want to generate in my supplier table different supplier records for each product, instead I want to have only 5 records (5 suppliers) in my supplier table which are associated to every single product, it few words I want to achieve something like "one to all", is it possible to do it using JPA annotations?
Product entity
#Entity
public class Product {
#Id
private String productCode;
#OneToMany
#JoinColumn(name = "supplier_id", referencedColumnName = "productCode")
private List<Supplier> suppliers;
}
Supplier entity
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String name;
}
Unidirectional #OneToMany association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) // according to your need
private List<Supplier> suppliers;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
...
}
#ManyToOne association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "product_id", foreignKey = #ForeignKey(name = "PRODUCT_ID_FK"))
private Product product;
private String name;
...
}
Lets say I have bidirectional one-to-many association between Parent-Child, mapped as follows:
public class TradingAccount {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "tradingAccount", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UnderlyingPerTradingAccount> underlyingPerTradingAccounts;
#Version
private Long version;
}
and
public class UnderlyingPerTradingAccount {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
private TradingAccount tradingAccount;
private Boolean enableBuy;
private Boolean enableSell;
}
now when i update a TradingAccount this exeception I get exception:
object references an unsaved transient instance - save the transient instance before flushing
I have a scenerio where one staff can belong to multiple organisation and for each organisation he can have different role. How can i map this in jpa?
Staff.java
public class Staff {
#ManyToMany
#JoinTable(name="STAFF_ORGANIZATION",joinColumns=#JoinColumn(name="staff_id"),inverseJoinColumns=#JoinColumn(name="organization_id"))
private Set<Organization> organizations;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
}
Organization.java
public class Organization {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String OrganizationName;
#ManyToMany(mappedBy="organizations")
private Set<Staff> staff;
}
StaffRoles.java
public class StaffRoles {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
#Enumerated(EnumType.ORDINAL)
private Roles roles;
public enum Roles {
USER(100), ADMIN(200);
private int values;
Roles(int values) {
this.values = values;
}
public int getValues() {
return values;
}
}
Can anyone please help me in mapping the roles to the staff. So many staff can belong to many organisation and for each organisation he can have different role.
Any help will be highly appreciated!
Althought this question is not written clearly I will answer your question based on what I have understood.
Below is an ER-diagram for how your tables might look like.
Now you just need to create the classes needed.
User.java
Organization.java
UserOrganization.java
UserRole.java
Connect the right instance variables now via ManyToMany and OneToOne to achieve your goal.
EDIT:
After the question has been updated with more specific information, I can aid more in this answer. First make a StaffOrganizationRoles class that will sit between StaffOrganization and Roles. Next, make StaffOrganization sit between Staff and Organization, which means that instead of ManyToMany it will be ManyToOne from Staff -> StaffOrganization, and ManyToOne from Organization > StaffOrganization.
public class StaffOrganizationRoles {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "stafforganization_id", unique = false, nullable = false)
private StaffOrganization user;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "role_id", unique = false, nullable = false)
private Role role;
}
Staff organization class:
public class StaffOrganization {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "staff_id", unique = false, nullable = false)
private Staff staff;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "organization_id", unique = false, nullable = false)
private Organization organization;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "staffOrganization")
private Set<StaffOrganizationRoles> staffOrganizationRoles = new HashSet<>(0);
}
I've edited the picture above to represent the new ER-diagram.
Hope this will help you now.
public class Customer implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idCustomer")
private Integer idCustomer;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idCustomer")
private Collection<Login> loginCollection;
}
public class Login implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idLogin")
#JoinColumn(name = "idCustomer", referencedColumnName = "idCustomer")
#ManyToOne(optional = false)
private Customer idCustomer;
}
//trying to save the customer and login in the database
ArrayList<Login> logins = new ArrayList<Login>();
Login log = new Login();
log.setIdCustomer(cust);
logins.add(log);
cust.setLoginCollection(logins);
cust = custRepo.save(cust); //failed
//Login log = new Login();
//log.setUName(user);
//log.setPassword(pass);
//log.setIdCustomer(cust);
//cust = custRepo.save(cust);
//logRepository.save(log); //failed too.
I'm using spring data in my project. I have 2 model classes Customer and Login. My login class has a foreign key idCustomer in the database. When I try to save the customer without a login, it works fine but the problem is that I can't save a login object in the database.
I'm getting an error saying
Unknown column 'id_customer' in 'field list'
the jpa entities are generated.
Here is an image actual database.
Too many idCustomers in your example.
Try the code below.
I have changed a bit the annotated members #OneToMany and #ManyToOne,
following the tips established here JPA JoinColumn vs mappedBy
Also I have included idLogin in Login class. I don't know if this was a typo in your code.
public class Customer implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idCustomer")
private Integer idCustomer;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "customer")
private Collection<Login> loginCollection;
}
public class Login implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idLogin")
private Integer idLogin;
#ManyToOne
#JoinColumn(name="idCustomer", insertable=false, updatable=false)
private Customer customer;
}
You need to you annotation
#JoinColumn
please go through these
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumns.html
http://docs.oracle.com/javaee/6/api/javax/persistence/JoinColumn.html
I am currently developing a java ee application but i am having problems with the JPA.
I have two entities:
#Entitiy
public class Restaurant implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Desk> desks;
}
#Entitiy
public class Desk implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
}
And i am storing the desks with the following code:
Desk desk = new Desk();
desk.setNumber(Integer.toString(x));
desk.setRestaurant(restaurant);
em.persist(desk);
But now the strange thing is that the list of desks in the entity restaurant is empty but the restaurant value in the entity desk is correct.
The Database shema looks like that:
RESTAURANT (ID)
DESK (ID, RESTAURANT_ID)
RESTAURANT_DESK (RESTAURANT_ID, DESK_ID)
The table RESTAURANT_DESK is always empty. Why is this third table generated? And why is the list of desks in the entity restaurant empty?
For a bi-directional mapping, you need to give mappedBy attribute in the Restaurant entity to indicate the inverse relationship:
#Entity
public class Restaurant implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="restaurant")
private List<Desk> desks;
}
I found the problem. I had to add the entity desk also to the restaurant list.
Desk desk = new Desk();
desk.setNumber(Integer.toString(x));
desk.setRestaurant(restaurant);
restaurant.getDesks().add(desk);
em.persist(desk);