I have entity Account, Role, AccountRole.
#Entity
public class Account {
#Id
private String loingId;
private String username;
private String password;
private String email;
private boolean enable;
#OneToMany(mappedBy = "account", orphanRemoval = true)
private List<AccountRole> accountRoles = new ArrayList<>();
public String getLoingId() {
return loingId;
}
public void setLoingId(String loingId) {
this.loingId = loingId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<AccountRole> getAccountRoles() {
return accountRoles;
}
public void setAccountRoles(List<AccountRole> accountRoles) {
this.accountRoles = accountRoles;
}
public void addAccountRoles(AccountRole accountRoles) {
if (this.accountRoles == null){
this.accountRoles = new ArrayList<>();
}
this.accountRoles.add(accountRoles);
accountRoles.setAccount(this);
}
public void removeAccountRoles(){
this.accountRoles = null;
}
}
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String description;
private boolean enable;
#OneToMany(mappedBy = "role")
private List<AccountRole> accountRoles = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<AccountRole> getAccountRoles() {
return accountRoles;
}
public void setAccountRoles(List<AccountRole> accountRoles) {
this.accountRoles = accountRoles;
}
}
#Entity
public class AccountRole implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "account_id")
private Account account;
#ManyToOne
#JoinColumn(name = "role_id")
private Role role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
To create account with role is OK.
There is a problem in update.
I want to delete the existing Role and only add the changed Role when the Role of the Account is changed. However, existing data is not deleted from the AccoutRole table.
How can I solve the problem?
springBootVersion = '1.5.3.RELEASE'
java 1.8
gradle dependencies
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
testCompile('org.springframework.boot:spring-boot-starter-test')
runtime ('org.mariadb.jdbc:mariadb-java-client')
}
A couple of ideas:
Thought 1: Try using cascade
Yes, JPA 2.0 should handle this with orphanRemoval = true, but let's just see if that works. I think that it is not because you aren't creating an orphan here. The mapping is still "valid" from a relational perspective.
#OneToMany(mappedBy = "account", cascade = CascadeType.ALL) // or CascadeType.REMOVE
private List<AccountRole> accountRoles = new ArrayList<>();
Thought 2: Try setting the account roles to an empty hashmap instead first:
account.setAccountRoles(new HashMap<AccountRole>());
account.getAccountRoles().add(accountRole);;
Related
Need to make a selection of data from the related tables of the many-to-many relationship type.
How can you make data selection from tables in a many-to-many relationship
using jpa?
Gives an ERROR error: Table 'tets.usergroup' does not exist.
I was looking for the answer in Google, but Google did not help. I tried to prescribe the essence differently, it also did not help.
#Entity
#Table(name = "USERS")
public class User {
private long id;
private String username;
private String password;
private String email;
private Set<UserGroup> userGroups = new HashSet<UserGroup>();
public User() {
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public void addGroup(UserGroup group) {
this.userGroups.add(group);
}
#Id
#GeneratedValue
#Column(name = "USER_ID")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToMany(mappedBy = "user")
public Set<UserGroup> getUserGroups() {
return userGroups;
}
public void setUserGroups(Set<UserGroup> groups) {
this.userGroups = groups;
}
public void addUserGroup(UserGroup userGroup) {
this.userGroups.add(userGroup);
}
}
UserGroup class
#Entity
#Table(name = "USERS_GROUPS")
public class UserGroup {
private long id;
private User user;
private Group group;
// additional fields
private boolean activated;
private Date registeredDate;
#Id
#GeneratedValue
#Column(name = "USER_GROUP_ID")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "USER_ID")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "GROUP_ID")
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
public boolean isActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
#Column(name = "REGISTERED_DATE")
#Temporal(TemporalType.DATE)
public Date getRegisteredDate() {
return registeredDate;
}
public void setRegisteredDate(Date registeredDate) {
this.registeredDate = registeredDate;
}
}`#Entity
#Table(name = "GROUPS")
public class Group {
private long id;
private String name;
private Set<UserGroup> userGroups = new HashSet<UserGroup>();
public Group() {
}
public Group(String name) {
this.name = name;
}
#Id
#GeneratedValue
#Column(name = "GROUP_ID")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "group")
public Set<UserGroup> getUserGroups() {
return userGroups;
}
public void setUserGroups(Set<UserGroup> groups) {
this.userGroups = groups;
}
public void addUserGroup(UserGroup userGroup) {
this.userGroups.add(userGroup);
}
}`
And some exception
ERROR: Table 'tets.usergroup' doesn't exist
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:82)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:61)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2040)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1837)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1816)
at org.hibernate.loader.Loader.doQuery(Loader.java:900)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342)
at org.hibernate.loader.Loader.doList(Loader.java:2526)
at org.hibernate.loader.Loader.doList(Loader.java:2512)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2342)
at org.hibernate.loader.Loader.list(Loader.java:2337)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1833)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:231)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:157)
at net.codejava.hibernate.Many2ManyTester.select_filter(Many2ManyTester.java:184)
at net.codejava.hibernate.Many2ManyTester.main(Many2ManyTester.java:216)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'tets.usergroup' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4190)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4122)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2818)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2157)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2324)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:56)
... 15 more
I saw that you config the entity with table name:
#Table(name = "USERS_GROUPS")
but the error is:
error: Table 'tets.usergroup' does not exist
So maybe you made wrong query. Or you can find all places which use 'usergroup'
I'm using servlets with JPA+Hibernate). I don't understand the error, unless I've tried other solutions suggested in this forum. In fact, I don't want to store the UserAccount class as an entity; but I just want to declare it in the Utilisateur class (the Ids of the Utilisateur class are declared in the useraccount class).
My code :
#Entity
#Table(name = "utilisateur")
public class Utilisateur implements Serializable {
#Id
private UserAccount userAccount;
private Civility civility;
private Address address;
private Contact contact;
#Column(name = "sessions")
private List<String> sessions;
#Column(name = "particularRules")
private boolean particularRules;
public Utilisateur(UserAccount pAccount, Civility pCivility,
Address pAddress, Contact pContact, List<String>
pSessions,
boolean particularRules) {
this.userAccount = pAccount;
this.civility = pCivility;
this.address = pAddress;
this.contact = pContact;
this.sessions = pSessions;
this.particularRules = particularRules;
}
public Civility getCivility() {
return civility;
}
public void setCivility(Civility civility) {
this.civility = civility;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public boolean isParticularRules() {
return particularRules;
}
public void setParticularRules(boolean particularRules) {
this.particularRules = particularRules;
}
public UserAccount getUserAccount() {
return userAccount;
}
public void setUserAccount(UserAccount userAccount) {
this.userAccount = userAccount;
}
public List<String> getSessions() {
return sessions;
}
public void setSessions(List<String> sessions) {
this.sessions = sessions;
}
}
#Embeddable
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class UserAccount implements Serializable {
public UserAccount() {
}
public UserAccount(String pId, String pEmail, String pwsd, Date pCreaDate, Date pLastModDate) {
this.identifier = pId;
this.email = pEmail;
this.password = pwsd;
this.creationDate = pCreaDate;
this.lastModificationDate = pLastModDate;
}
#OneToOne(mappedBy = "userAccount", cascade = CascadeType.ALL,
fetch = FetchType.EAGER, orphanRemoval = true, targetEntity =
Utilisateur.class)
private Utilisateur user;
#Column(name = "creationDate")
#Temporal(javax.persistence.TemporalType.DATE)
private Date creationDate;
#Column(name = "lastModificationDate")
#Temporal(javax.persistence.TemporalType.DATE)
private Date lastModificationDate;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "identifier", nullable = false)
private String identifier;
#Column(name = "email")
private String email;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "password", nullable = false)
private String password;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Date getLastModificationDate() {
return lastModificationDate;
}
public void setLastModificationDate(Date lastModificationDate) {
this.lastModificationDate = lastModificationDate;
}
public Utilisateur getUser() {
return user;
}
public void setUser(Utilisateur user) {
this.user = user;
}
}
You must use an Embedded Primary Key.
See the answer to this question here in Stackoverflow How to create and handle composite primary key in JPA.
Best regards!
It may occur when Embedded Primary Key contains #EmbeddedId. Sub-composite key should be annotated with #Embedded instead.
I have started testing with spring boot to create a Restful webservice that has
simple crud functions.i have two entity classes
Company.java
#Entity
#Table(name="Company_new")
public class Company {
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void setId(int id) {
this.id = id;
}
#NotNull
#Column(name="name")
private String name;
#OneToMany(mappedBy="company",cascade=CascadeType.ALL)
private Set<User> users;
public Company(String name){
this.name = name;
}
public Company(){
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public int getId(){
return id;
}
}
and User.java
#Entity
#Table(name="user_new")
public class User {
#Id
#Column
#GeneratedValue(strategy = GenerationType.AUTO)
private int idUser;
#NotNull
#Column
private String name;
#NotNull
#Column
private String userName;
#NotNull
#Column
private String authLevel;
#Column
private String password;
#ManyToOne
#JoinColumn(name="idCompany")
private Company company;
// Public methods
public Company getCompany(){
return company;
}
public void setCompany(Company company){
this.company = company;
}
public void setName(String name){
this.name =name;
}
public void setUserName(String userName){
this.userName = userName;
}
public String getName(){
return this.name;
}
public String getUsername(){
return this.userName;
}
public String getPassword(){
return this.password;
}
public String getAuthLevel() {
return authLevel;
}
public void setAuthLevel(String authLevel) {
this.authLevel = authLevel;
}
public String getUserName() {
return userName;
}
public void setId(int idUser) {
this.idUser = idUser;
}
public void setPassword(String password) {
this.password = password;
}
public int getId(){
return this.idUser;
}
}
i want to have a relationship with a Company having many users.
I have tried presisting a user record like this
#Autowired
CompanyDao companyDao;
#RequestMapping(value = "/user/create", method = RequestMethod.POST)
public #ResponseBody ResponseEntity createUser(#RequestBody User user) {
try {
Company c = companyDao.findOne(user.getCompany().getId());
user.setCompany(c);
userDao.save(user);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(user, HttpStatus.OK);
}
my data is presisting in the database the way i want
but when i try to access a company record it loads like this
obviously it loads relationships in a cycle and eventually gives stack overflow error. how to solve this ?
Depending on your desired outcome you can:
use #JsonIgnore on public Set<User> getUsers() to prevent serializing the users collection or #JsonIgnore on public Company getCompany() to prevent company serialization
use #JsonManagedReference on public Set<User> getUsers() and #JsonBackReference on public Company getCompany() to let Jackson know that it's a bidirectional relation.
PS. If the API you're exposing will be consumed by code you do not control consider not exposing entities directly but mapping them to DTOs
I have the following Entity classes UserEntity and TicketEntity. A User has many tickets and many tickets can belong to a user. My question is, is there a way to automatically load all the tickets belonging to a pertaining user by using Hibernate or do I have to manually load all the entity relationships from the DB? I think the .load() does this but I'm not quite sure. In my case could I do something like
userEntity.load()
Any help is appreciated, thanks
UserEntity.java
package com.issuetracking.domain;
/**
*/
import java.util.List;
import javax.persistence.*;
#Entity
#Table(name="user")
public class UserEntity {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="firstname")
private String firstname;
#Column(name="lastname")
private String lastname;
#Column(name="username")
private String username;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Transient
private String confirmpassword;
#Column(name="verified")
private boolean verified;
#Column(name="role_id")
private int role_id;
#OneToMany(fetch = FetchType.LAZY)
private List<TicketEntity> tickets;
//Getters/Setters
public List<TicketEntity> getTickets() {
return tickets;
}
public void setTickets(List<TicketEntity> tickets) {
this.tickets = tickets;
}
public int getRole_id() {
return role_id;
}
public void setRole_id(int role_id) {
this.role_id = role_id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfirmpassword() {
return confirmpassword;
}
public void setConfirmpassword(String confirmpassword) {
this.confirmpassword = confirmpassword;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
}
TicketEntity.java
package com.issuetracking.domain;
import java.util.Date;
import javax.persistence.*;
#Entity
#Table(name="ticket")
public class TicketEntity {
#Id
#Column(name="ticket_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="date_created")
#Temporal( TemporalType.TIMESTAMP )
private Date date_created;
#Column(name="status_id")
private int status_id;
//private TicketStatus status;
#Column(name="urgency_id")
private int urgency_id;
#ManyToOne
#JoinColumn(name="user_id", insertable=false, updatable=false)
private UserEntity belongs_to;
#ManyToOne
#JoinColumn(name="user_id", insertable=false, updatable=false)
private UserEntity assigned_to;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate_created() {
return date_created;
}
public void setDate_created(Date date_created) {
this.date_created = date_created;
}
public int getStatus_id() {
return status_id;
}
public void setStatus_id(int status_id) {
this.status_id = status_id;
}
public int getUrgency_id() {
return urgency_id;
}
public void setUrgency_id(int urgency_id) {
this.urgency_id = urgency_id;
}
public UserEntity getBelongs_to() {
return belongs_to;
}
public void setBelongs_to(UserEntity belongs_to) {
this.belongs_to = belongs_to;
}
public UserEntity getAssigned_to() {
return assigned_to;
}
public void setAssigned_to(UserEntity assigned_to) {
this.assigned_to = assigned_to;
}
}
A User has many tickets and many tickets can belong to a user.
In this case relationship should be ManyToMany
My question is, is there a way to automatically load all the tickets belonging to a pertaining user
Use EAGER FetchType instead of LAZY , Like
#OneToMany(fetch = FetchType.EAGER)
private List<TicketEntity> tickets;
I have a user dao
#Entity
#Table(name="EBIGUSERTIM")
public class EbigUser {
private String id;
private Integer source;
private String entryscheme;
private String fullName;
private String email;
private Long flags;
private String status;
private String createdBy;
private Date createdStamp;
private String modifiedBy;
private Date modifiedStamp;
#Id
#Column(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
#Column(name="SOURCE")
public Integer getSource() {
return source;
}
public void setSource(Integer source) {
this.source = source;
}
#Column(name="ENTRYSCHEME")
public String getEntryscheme() {
return entryscheme;
}
public void setEntryscheme(String entryscheme) {
this.entryscheme = entryscheme;
}
#Column(name="FULLNAME")
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#Column(name="EMAIL")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name="FLAGS")
public Long getFlags() {
return flags;
}
public void setFlags(Long flags) {
this.flags = flags;
}
#Column(name="STATUS")
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
#Column(name="CREATEDBY")
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#Column(name="CREATEDSTAMP")
public Date getCreatedStamp() {
return createdStamp;
}
public void setCreatedStamp(Date createdStamp) {
this.createdStamp = createdStamp;
}
#Column(name="MODIFIEDBY")
public String getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
#Column(name="MODIFIEDSTAMP")
public Date getModifiedStamp() {
return modifiedStamp;
}
public void setModifiedStamp(Date modifiedStamp) {
this.modifiedStamp = modifiedStamp;
}
i am selecting 2 rows out of the db. The sql works
select * from ebigusertim where id='blah'
It returns 2 distinct rows. When i query the data using hibernate, it appears that the object memory is not being allocated for each entry in the list. Thus, i get 2 entries in the list with the same object.
Criteria userCriteria = session.createCriteria(EbigUser.class);
userCriteria.add(Restrictions.eq("id", id));
userlist = userCriteria.list();
Why are you defining two id columns(both id and source are mapped with annotation #Id)?
#Id
#Column(name="ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
#Column(name="SOURCE")
public Integer getSource() {
return source;
}
Please remove one if it is by mistake. If both together make composite key, map them accordingly e.g.
#Embeddable
public class UserPK implements Serializable {
#Column(name = "ID", nullable = false)
private String id;
#Column(name = "SOURCE", nullable = false)
private Integer source;
.....
.....
}
Use this new class in you original class as Id as below:
#EmbeddedId
private UserPK userPK;
Hope this helps.