I am trying to delete an object in my database having a foreign key row in other table the error is IllegalArgumentException occurred calling getter of com.techpro.webstat.models.Role.username; nested exception is org.hibernate.PropertyAccessException
i have 2 entities :
import javax.persistence.*;
#Entity
#Table(name = "users")
public class User {
public Role ro;
public int user_id;
public String username;
public String password;
public int enabled = 1;
public User() {
}
public User(String username, String password, int enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "username", referencedColumnName = "username", insertable = false, updatable = false)
public Role getRo() {
return ro;
}
public void setRo(Role ro) {
this.ro = ro;
}
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "enabled")
public int getEnabled() {
return enabled;
}
public void setEnabled(int enabled) {
this.enabled = enabled;
}
}
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name = "user_roles")
public class Role implements Serializable {
public int user_role_id;
public String username;
public String role;
public User user;
public void setUser_role_id(int user_role_id) {
this.user_role_id = user_role_id;
}
#OneToOne(mappedBy = "ro", cascade = CascadeType.ALL)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Role(String username, String role) {
this.username = username;
this.role = role;
}
public Role() {
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getUser_role_id() {
return user_role_id;
}
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "role")
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
and this is my code to delete user object :
#RequestMapping( value = "/deleteuserid/{user_id}", method = RequestMethod.GET)
public ModelAndView doDelete(#PathVariable("user_id") int user_id){
ModelAndView mv = new ModelAndView("redirect:/utilisateurs");
appRepo.delete(user_id);
return mv;
}
Related
I want to delete an instance of "UserRegistration" which has a reference to an instance of "Authority". When deleting the instance of "UserRegistration" via the repository I get following Error:
"Cannot delete or update a parent row: a foreign key constraint fails (seprojekt.authorities, CONSTRAINT authorities_ibfk_1 FOREIGN KEY (userid) REFERENCES users (id))"
Is there a possibility of deleting the referenced Entity when the Instance of "UserRegistration" ist deleted? I tried this with Cascadetype and orphanRemoval in "UserRegistration" but nothing happened.
The Method which tries to delete the Entity:
#DeleteMapping
public boolean deleteUser(#RequestParam String username) {
Optional<UserRegistration> optUserRegistration = uRepo.findByUsername(username);
if(optUserRegistration.isPresent()) {
System.out.println("!!! Authority is: '" + optUserRegistration.get().getAuthority().getAuthority());
uRepo.delete(optUserRegistration.get());
return true;
}
return false;
}
The UserRegistrationclass looks like this:
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
#Entity
#Table(name = "users")
public class UserRegistration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
#JsonIgnore
private String password;
#JsonIgnore
private boolean enabled;
private Integer profilePicture;
private String email;
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "id")
private Authority authority;
#JsonManagedReference
#ManyToMany
#JoinTable(name = "userhasfavorite", joinColumns = #JoinColumn(name = "userid"), inverseJoinColumns = #JoinColumn(name = "channelid"))
private List<Channel> favorites;
public UserRegistration() {
}
public UserRegistration(String email, String username, String password, boolean enabled, int profilePicture) {
this.email = email;
this.username = username;
this.password = password;
this.enabled = enabled;
this.profilePicture = profilePicture;
}
public int getId() {
return id;
}
public void setId(int 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 boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Integer getProfilePicture() {
return profilePicture;
}
public void setProfilePicture(Integer profilePicture) {
this.profilePicture = profilePicture;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Authority getAuthority() {
return authority;
}
public void setAuthority(Authority authority) {
this.authority = authority;
}
public List<Channel> getFavorites() {
return favorites;
}
public void setFavorites(List<Channel> favorites) {
this.favorites = favorites;
}
}
The Authorityclass looks like this:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "authorities")
public class Authority {
#Id
#Column(name = "userid")
private int userID;
private String username;
private String authority;
#OneToOne(mappedBy = "authority")
private UserRegistration user;
public Authority() {
}
public Authority(int userID, String username, String authority) {
this.userID = userID;
this.username = username;
this.authority = authority;
}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public UserRegistration getUser() {
return user;
}
public void setUser(UserRegistration user) {
this.user = user;
}
}
Thanks a lot for reading this. Please ask me for more details if required.
In order for cascading to work; you need to reverse the entity relation definition. The cascading only works for parent entity to child entity. What I mean is the following. Please define authority in UserRegistration as:
#OneToOne(mappedBy="user", cascade = CascadeType.ALL)
private Authority authority;
and the userRegistration in Authority as:
#OneToOne
#MapsId
private UserRegistration user;
I believe this should work. Take a look at the following for more information. Hope that helps.
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);;
i have this error nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): app.Spring.domain.UserDetails.
I now have this user table and in profile i want to edit this UserDetails.
i was trying with GeneratedValue but this doing random id that not associate with user_id also checked generator but this method also dont work.There is so many options so i am lost now.Can someone show some method to mapp this two entities?
User
#Entity
#Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "user_id")
private Long user_id;
#NotBlank
#Size(min = 5, max = 20)
private String username;
#NotBlank
#Size(min = 8, max = 20)
private String password;
private String email;
private String name;
private String surname;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private UserDetails userDetail;
public User() {
}
public User(Long user_id, String username, String email, String name,
String surname, UserDetails userDetail, String password) {
super();
this.user_id = user_id;
this.username = username;
this.email = email;
this.name = name;
this.surname = surname;
this.userDetail = userDetail;
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Long getUser_id() {
return user_id;
}
public final void setUser_id(Long user_id) {
this.user_id = user_id;
}
public void setId(Long user_id) {
this.user_id = user_id;
}
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
User_Details
#Entity
#Table(name = "user_address")
public class UserDetails {
public UserDetails() {
super();
// TODO Auto-generated constructor stub
}
#Id
#Column(name = "user_id")
private Long id;
private String adres1;
private String adres2;
private String city;
private String postcode;
#OneToOne
#PrimaryKeyJoinColumn
private User user;
public UserDetails(Long id, String adres1, String adres2, String city,
String postcode, User user) {
super();
this.id = id;
this.adres1 = adres1;
this.adres2 = adres2;
this.city = city;
this.postcode = postcode;
this.user = user;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAdres1() {
return adres1;
}
public void setAdres1(String adres1) {
this.adres1 = adres1;
}
public String getAdres2() {
return adres2;
}
public void setAdres2(String adres2) {
this.adres2 = adres2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public void setId(Long id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
LOGIC
#RequestMapping(value = "/userDetails", method = RequestMethod.GET)
public String showForm(Model model,
#RequestParam(value = "id", defaultValue = "-1") Long id,
HttpSession session) {
app.Spring.domain.UserDetails va = (id > 0) ? reg.getAdress(id)
: new UserDetails();
model.addAttribute("detal", va);
return "userDetails";
}
#RequestMapping(value = "/userDetails", method = RequestMethod.POST)
public String submit(Model model, #ModelAttribute("detal") UserDetails va,
BindingResult result) {
validator.validate(va, result);
if (result.hasErrors()) {
return "userDetails";
}
reg.saveOrUpdateUserDetails(va);
return "profile";
}
I don't know how to do this with annotations but you might try to manually assign the (hopefully then already present) id fetched from user in the UserDetails entity in the #PrePresist annotated method.
User
#Entity
#Table(name = "USERS")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "user_id")
private Long user_id;
#NotBlank
#Size(min = 5, max = 20)
private String username;
#NotBlank
#Size(min = 8, max = 20)
private String password;
private String email;
private String name;
private String surname;
#OneToOne(mappedBy = "user")
private UserDetails userDetail;
User_detail
#Entity
#Table(name = "user_address")
public class UserDetails {
public UserDetails() {
super();
// TODO Auto-generated constructor stub
}
#Id
private Long id;
private String adres1;
private String adres2;
private String city;
private String postcode;
#OneToOne
#JoinColumn(name = "user_id")
private User user;
ive been working on this for a while and can't seem to figure it out except that at some point it was working as was intended. I have two objects, a User which can be associatted with multiple addresses. Saving a new user and address together works just fine, but when i try to add a new address to an existing User i get an error about duplicate primary keys for User table. I guess it has something to do with the configuration in hibernate trying both unidirectional and bidirectional.
Below are any relevant files. Thanks of your help!
User.java
#Entity
#Table(name = "users")
public class Users implements Serializable {
private static final long serialVersionUID = -5699491123012997265L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int idusers;
#NotBlank(groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
#Size(min = 5, max = 15, groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
#Pattern(regexp = "^\\w{5,}$", groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
private String username;
#NotBlank(groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
#Pattern(regexp = "^\\S+$", groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
#Size(min = 8, max = 15, groups = { FormValidationGroup.class })
private String password;
private boolean enabled = false;
private String authority;
#Size(max = 25, groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
private String name;
#Size(min = 10, max = 10, groups = { PersistenceValidationGroup.class, FormValidationGroup.class })
private String phoneNo;
#OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
#JoinColumn(name = "idaddresses")
private Set<Addresses> addresses;
// CONSTRUCTORS
public Users() {
}
public Users(String username, String password, boolean enabled,
String authority, String name, String phoneNo,
Set<Addresses> addresses) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.authority = authority;
this.name = name;
this.phoneNo = phoneNo;
this.addresses = addresses;
}
// GETTERS AND SETTERS
public int getIdUsers() {
return idusers;
}
public void setIdusers(int idusers) {
this.idusers = idusers;
}
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 boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIdusers() {
return idusers;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public Set<Addresses> getAddresses() {
return addresses;
}
public void setAddresses(Set<Addresses> addresses) {
this.addresses = addresses;
}
public void addAddress(Addresses addresses) {
if (this.addresses == null) {
this.addresses = new HashSet<Addresses>();
}
addresses.setUsers(this);
this.addresses.add(addresses);
}
}
Addresses.java
#Entity
#Table(name = "addresses")
public class Addresses implements Serializable {
private static final long serialVersionUID = -1239830513656245466L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int idaddresses;
#NotBlank
#Size(min = 5, max = 45)
private String street1;
#NotBlank
#Size(min = 5, max = 45)
private String street2;
#Size(min = 0, max = 200)
private String special;
private String apt;
private String city;
private String state;
#ManyToOne
#JoinColumn(name = "idusers")
private Users users;
// CONSTRUCTORS
public Addresses() {
}
public Addresses(String street1, String street2, String special,
String apt, String city, String state, Users users) {
this.street1 = street1;
this.street2 = street2;
this.special = special;
this.apt = apt;
this.city = city;
this.state = state;
this.users = users;
}
// GETTERS AND SETTERS
public int getIdaddresses() {
return idaddresses;
}
public void setIdaddresses(int idaddresses) {
this.idaddresses = idaddresses;
}
public String getStreet1() {
return street1;
}
public void setStreet1(String street1) {
this.street1 = street1;
}
public String getStreet2() {
return street2;
}
public void setStreet2(String street2) {
this.street2 = street2;
}
public String getSpecial() {
return special;
}
public void setSpecial(String special) {
this.special = special;
}
public String getApt() {
return apt;
}
public void setApt(String apt) {
this.apt = apt;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Users getUsers() {
return users;
}
public void setUsers(Users users) {
this.users = users;
}
}
Part of flow that calls method
<view-state id="newAddress" model="address">
<transition on="addNewAddress" to="customerReady" />
<on-exit>
<evaluate expression="address.street1 = requestParameters.street1"></evaluate>
<evaluate expression="address.street2 = requestParameters.street2"></evaluate>
<evaluate expression="address.apt = requestParameters.apt"></evaluate>
<evaluate expression="address.city = requestParameters.city"></evaluate>
<evaluate expression="address.special = requestParameters.special"></evaluate>
<evaluate expression="address.city = requestParameters.city"></evaluate>
<evaluate expression="address.state = 'NY'"></evaluate>
<evaluate expression="user.addAddress(address)"></evaluate>
<evaluate expression="usersService.update(user)"></evaluate>
</on-exit>
</view-state>
userService.update(user) sends you to dao
public void update(Users users) {
session().saveOrUpdate(users);
}
Function in my DAO (findByUsername) is always returning 0 rows no matter if I change the entity class, even after removing annotation from the entity there is no exception, just 0 rows. This code is implemented in the spring based app according to some examples I have found.
DAO:
#Repository("userDao")
public class UserDao extends CustomHibernateDaoSupport {
public void save(User user) {
getHibernateTemplate().save(user);
}
public void delete(User user) {
getHibernateTemplate().delete(user);
}
public User findByUsername(String username) throws DataNotFoundException {
Session session = getSession();
Criteria crit = session.createCriteria(User.class);
System.out.println(username);
crit.add(Restrictions.eq("username", username));
crit.setMaxResults(1);
List<User> users = crit.list();
System.out.println(users);
if (users.size() < 1) {
throw new DataNotFoundException();
}
return users.get(0);
}
}
ENTITY:
#Entity
#Table(name = "users")
public class User {
private Integer id;
private String username;
private String password;
private boolean active;
private String activationCode;
private Date createdAt;
private String email;
private Set<Wall> walls = new HashSet<Wall>();
#Id
#GeneratedValue
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "username", unique = true, nullable = false)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "active")
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
#Column(name = "activation_code")
public String getActivationCode() {
return activationCode;
}
public void setActivationCode(String activationCode) {
this.activationCode = activationCode;
}
#Column(name = "created_at", columnDefinition = "DATETIME")
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "users_has_walls", joinColumns = {
#JoinColumn(name = "user_id", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "wall_id",
nullable = false, updatable = false) })
public Set<Wall> getWalls() {
return walls;
}
public void setWalls(Set<Wall> walls) {
this.walls = walls;
}
}
The solution was to change import declaration to
import javax.persistence.Entity;
instead of hibernate.
User entity class was not imported.