could not resolve property: userId.username - java

I have following entity classes:
#MappedSuperclass
public class AbstractEntity implements Serializable, Comparable<AbstractEntity> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
protected Integer id;
#Override
public int compareTo(AbstractEntity o) {
return this.toString().compareTo(o.toString());
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
#Entity
#Table(name = "ticket")
#NamedQueries({
#NamedQuery(name = "Ticket.findAll", query = "SELECT t FROM Ticket t")})
public class Ticket extends AbstractEntity {
#Column(name = "title")
private String title;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private TicketStatus status;
#Enumerated(EnumType.STRING)
#Column(name = "priority")
private TicketPriority priority;
#Column(name = "categories")
private String categories;
#Column(name = "views")
private Integer views;
#Column(name = "date_time_created")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeCreated;
#Column(name = "date_time_modified")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeModified;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketFollower> ticketFollowerList;
#JoinColumn(name = "project_id", referencedColumnName = "id")
#ManyToOne(optional = false)
private Project projectId;
#JoinColumn(name = "ticket_attachment_id", referencedColumnName = "id")
#ManyToOne
private TicketAttachment ticketAttachmentId;
#JoinColumn(name = "user_id", referencedColumnName = "id")
#ManyToOne(optional = false)
private User userId;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketComment> ticketCommentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketAttachment> ticketAttachmentList;
#Inject
public Ticket() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
...
#Override
public String toString() {
return getTitle();
}
}
#Entity
#Table(name = "user")
#NamedQueries({
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")})
public class User extends AbstractEntity {
#Enumerated(EnumType.STRING)
#Column(name = "role")
private Role role;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "avatar_path")
private String avatarPath;
#Column(name = "date_time_registered")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeRegistered;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketFollower> ticketFollowerList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<Ticket> ticketList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketComment> ticketCommentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<ProjectFollower> projectFollowerList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketAttachment> ticketAttachmentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<Project> projectList;
#Inject
public User() {}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
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 getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
I get this exception from creating a hibernate Criteria. In my TicketDao class I have a method which search ticket by username, and when I invoke code below
Criteria criteria = session.createCriteria(Ticket.class);
criteria.add(Restrictions.eq("userId.username", username));
it throws exception:
could not resolve property: userId.username of: com.entities.Ticket
However, when I write criteria like:
criteria.add(Restrictions.eq("userId.id", userId));
it does not show any exception and returns me result. Any idea why my syntax for criteria.add(Restrictions.eq("userId.username", username)); and other properties like firstname, last name is wrong ?

Criteria does not work like EL or Java methods or attributes, you cannot refer to inner objects with a dot ..
You have to create a restriction in Ticket, right? What does Ticket has? An User. Then... you have to create a new User, set the username to this User and then set the created User to Ticket's criteria:
Criteria criteria = session.createCriteria(Ticket.class);
User user = new User();
user.setUsername(username);
criteria.add(Restrictions.eq("user", user));

Related

Update User Details api returns TransientPropertyValueException:

I'm setting an API endpoint that updates an existing user detail, to do that I try to fetch an existing user from the database by id, when I start the application and test with postman it runs the query on my console but displays TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing and fails to make the intended updates. Here is my code
Member
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name ="member",
indexes = {
#Index(
columnList = "email_address",
name = "email_address_idx",
unique = true
),
},
uniqueConstraints = {
#UniqueConstraint(
columnNames = {"email_address", "phone_number"},
name = "email_address_phone_number_uq"
)
}
)
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "nationality_id")
private Country nationality;
#ManyToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "country_of_residence_id")
private Country countryOfResidence;
#Temporal(TemporalType.DATE)
#Column(name ="date_of_birth")
private Date dateOfBirth = new Date();
#Column(name ="current_job_title")
private String currentJobTitle;
#Column(name = "email_address", nullable = false)
private String emailAddress;
#Column(name = "username")
private String username;
#Column(name ="phone_number")
private String phoneNumber;
#Column(name ="city")
private String city;
#Column(name ="state")
private String state;
#Column(name ="password", nullable = false)
private String password;
#Column(name ="avatar")
private String avatar;
#Column(name ="active", nullable = false)
private Boolean active = true;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_on", updatable = false, nullable = false)
private Date createdOn;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_on", nullable = false)
private Date updatedOn;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "member_roles",
joinColumns = #JoinColumn(
name = "member_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles = new HashSet<>();
public void addRole(Role role) {
this.getRoles().add(role);
}
public void clearRoles() {
this.roles = new HashSet<>();
}
}
MemberDto
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class UpdateMemberDto {
#NotNull(message = "{member.first_name.notNull}")
private String firstName;
#NotNull(message = "{member.last_name.notNull}")
private String lastName;
private Date dateOfBirth;
private String currentJobTitle;
#NotNull(message = "{member.email_address.notNull}")
private String emailAddress;
private String username;
#NotNull(message = "{member.phone_number.notNull}")
private String phoneNumber;
private String city;
private String state;
private String password;
private String avatar;
private Boolean active;
}
ServiceImpl
#Slf4j
#Service
public class UpdateMemberServiceImpl implements UpdateMemberService {
#Autowired
private ModelMapper modelMapper;
private final UpdateMemberRepository repository;
private final MemberJpaRepository jpaRepository;
public UpdateMemberServiceImpl(UpdateMemberRepository repository, MemberJpaRepository jpaRepository) {
this.repository = repository;
this.jpaRepository = jpaRepository;
}
#Override
#Transactional
public Member update(Long id, UpdateMemberDto body) {
Optional<Member> existingMember = jpaRepository.findById(id);
if (existingMember != null) {
Member member = new Member();
member = modelMapper.map(body, Member.class);
member.setId(id);
member = jpaRepository.save(member);
return member;
}
throw new MemberNotFoundException(id);
}
}

How can I implement this Spring Data JPA query by method name that retrieve a specific object based on two properties?

I am working on a Spring Boot project using Spring Data JPA trying to adopt the "query by method name" style in order to define my queries into repositories.
I am finding some difficulties trying to implement a select query retrieving the list of objects based on two different "where condition". I will try to explain what I have to do.
First of all this is my main entity class named Wallet:
#Entity
#Table(name = "wallet")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Wallet implements Serializable {
private static final long serialVersionUID = 6956974379644960088L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "address")
private String address;
#Column(name = "notes")
private String notes;
#ManyToOne
#EqualsAndHashCode.Exclude // Needed by Lombock in "Many To One" relathionship to avoid error
#JoinColumn(name = "fk_user_id", referencedColumnName = "id")
#JsonBackReference(value = "user-wallets")
private User user;
#ManyToOne
#EqualsAndHashCode.Exclude // Needed by Lombock in "Many To One" relathionship to avoid error
#JoinColumn(name = "fk_coin_id", referencedColumnName = "id")
private Coin coin;
#ManyToOne
#JoinColumn(name = "type", referencedColumnName = "id")
private WalletType walletType;
public Wallet(String address, String notes, User user, Coin coin, WalletType walletType) {
super();
this.address = address;
this.notes = notes;
this.user = user;
this.coin = coin;
this.walletType = walletType;
}
}
As you can see a wallet is directly binded to a specific User object and to a specific Coin object.
For completeness this is the code of my User entity class:
#Entity
#Table(name = "portal_user")
#Getter
#Setter
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User implements Serializable {
private static final long serialVersionUID = 5062673109048808267L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name = "first_name")
#NotNull(message = "{NotNull.User.firstName.Validation}")
private String firstName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "surname")
#NotNull(message = "{NotNull.User.surname.Validation}")
private String surname;
#Column(name = "sex")
#NotNull(message = "{NotNull.User.sex.Validation}")
private char sex;
#Column(name = "birthdate")
#NotNull(message = "{NotNull.User.birthdate.Validation}")
private Date birthdate;
#Column(name = "tax_code")
#NotNull(message = "{NotNull.User.taxCode.Validation}")
private String taxCode;
#Column(name = "e_mail")
#NotNull(message = "{NotNull.User.email.Validation}")
private String email;
#Column(name = "pswd")
#NotNull(message = "{NotNull.User.pswd.Validation}")
private String pswd;
#Column(name = "contact_number")
#NotNull(message = "{NotNull.User.contactNumber.Validation}")
private String contactNumber;
#Temporal(TemporalType.DATE)
#Column(name = "created_at")
private Date createdAt;
#Column(name = "is_active")
private boolean is_active;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
#JsonManagedReference(value = "address")
private Set<Address> addressesList = new HashSet<>();
#ManyToMany(cascade = { CascadeType.MERGE })
#JoinTable(
name = "portal_user_user_type",
joinColumns = { #JoinColumn(name = "portal_user_id_fk") },
inverseJoinColumns = { #JoinColumn(name = "user_type_id_fk") }
)
private Set<UserType> userTypes;
#ManyToOne(fetch = FetchType.LAZY)
#JsonProperty("subagent")
private User parent;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
#JsonManagedReference(value = "user-wallets")
private Set<Wallet> wallets = new HashSet<>();
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
String email, String pswd, String contactNumber, Date createdAt, boolean is_active) {
super();
this.firstName = firstName;
this.middleName = middleName;
this.surname = surname;
this.sex = sex;
this.birthdate = birthdate;
this.taxCode = taxCode;
this.email = email;
this.pswd = pswd;
this.contactNumber = contactNumber;
this.createdAt = createdAt;
this.is_active = is_active;
}
}
and this is the code of my Coin entity class:
#Entity
#Table(name = "coin")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Coin implements Serializable {
private static final long serialVersionUID = 6956974379644960088L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "name")
#NotNull(message = "{NotNull.Coin.name.Validation}")
private String name;
#Column(name = "description")
private String description;
#Column(name = "code", unique = true)
#NotNull(message = "{NotNull.Coin.code.Validation}")
private String code;
#Type(type="org.hibernate.type.BinaryType")
#Column(name = "logo")
private byte[] logo;
}
Then I have this WalletRepository interface:
public interface WalletRepository extends JpaRepository<Wallet, Integer> {
}
Here I need to define a query by name method that retrieve a specific wallet of a specific User (I think that I can query by the id field of the User) and based and related to a specific Coin (I think that I can query by the id fied of the Coin).
How can I implement a behavior like this?
The following should work:
public interface WalletRepository extends JpaRepository<Wallet, Integer> {
List<Wallet> findByUserIdAndCoinId();
}
You can read more about this at:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords

List of roles as an argument

I want to assign role to a new user, the role is called ROLE_USER in database and has an id of 3. but I dont know how to pass that value in method save(). At the bottom, I throw the most important classes and save method.
User model class
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String lastName;
#Column(nullable = false, unique = true)
private String email;
#Column(nullable = false)
private String password;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "user_role",
joinColumns = {#JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
inverseJoinColumns = {#JoinColumn(name = "ROLE_ID", referencedColumnName = "ID")})
private List<Role> roles;
public User(String firstName, String lastName, String email, String password, List<Role> roles) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.roles = roles;
}
Getters and setters ...
Role model class
#Entity
#Data
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
#NotNull
private String name;
#ManyToMany(mappedBy="roles")
private List<Role> users;
}
UserRegistrationDto class
public class UserRegistrationDto {
private String firstName;
private String lastName;
private String email;
private String password;
private List<Role> roles;
}
method for save in UserService class
public User save(UserRegistrationDto registrationDto) {
User user = new User(registrationDto.getFirstName(),
registrationDto.getLastName(),
registrationDto.getEmail(),
passwordEncoder.encode(registrationDto.getPassword()),
ROLE ???);
return userRepository.save(user);
}

Spring is not using ManyToMany relationship

I have a user and a movie model:
user:
#Entity(name = "User")
#Table(name = "USER")
public class User {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
#SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
private Long id;
#Column(name = "USERNAME", length = 50, unique = true)
#NotNull
#Size(min = 4, max = 50)
private String username;
#Column(name = "PASSWORD", length = 100)
#NotNull
#Size(min = 4, max = 100)
private String password;
#Column(name = "FIRSTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String firstname;
#Column(name = "LASTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String lastname;
#Column(name = "EMAIL", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String email;
#Column(name = "ENABLED")
#NotNull
private Boolean enabled;
#Column(name = "LASTPASSWORDRESETDATE")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date lastPasswordResetDate;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "USER_AUTHORITY",
joinColumns = {#JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
inverseJoinColumns = {#JoinColumn(name = "AUTHORITY_ID", referencedColumnName = "ID")})
private List<Authority> authorities;
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 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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public Date getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Date lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
public Set<Movie> getMovies() {
return movies;
}
public void setMovies(Set<Movie> movies) {
this.movies = movies;
}
}
movie:
#Entity(name = "Movie")
#Table(name = "movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
public Movie(){}
public Movie(Integer id, String name ) {
this.id = id;
this.name = name;
}
#ManyToMany(mappedBy = "movies")
private Set<User> users;
public Set<User> getUsers() {
return users;
}
public void addUser(User user){
System.out.println("ADD MOVIE: " + user);
users.add(user);
user.getMovies().add(this);
}
public void setUsers(Set<User> users) {
this.users = users;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString(){
return "id: " + id + "name: " + name;
}
}
I've set up a many to many relation between these models. With, if I am correct, the user as the owner of the relation.
In my MovieController.java I have:
#RequestMapping(value = "/", method = RequestMethod.POST)
public Movie createMovie(#RequestBody Movie movie){
return movieService.createMovie(movie);
}
This calls the MovieService.java:
#Override
public Movie createMovie(Movie movie) {
return movieRepository.save(movie);
}
And this calls the MovieRepository.java:
#Repository
public interface MovieRepository extends CrudRepository<Movie, Serializable> {}
When I call the post methode from my front-end a movie record is saved in my movie table, but no record is created in the user_movie table. Doesn't Hibernate do this implicit since I set up a Many to Many relation between user and movie?
For the first view, your code is correct.
The problem can be in GenerationType.SEQUENCE (try to use GenerationType.AUTO for User's id), or you need to add #Transactional to your controller.
You save the movie and in order to also have the user saved the cascade has to be set in the movie. Otherwise you can keep the cascade in user and save him.
You need to put the cascade to the entity on which you call save to cascade it.
Movie{
#ManyToMany(mappedBy = "movies", cascade={CascadeType.ALL})
private Set<User> users;
public Set<User> getUsers() {
return users;
}
}
User {
#ManyToMany
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
}
Don't forget to add the user to movie and vice versa before saving.
As with all bi-directional relationships it is your object model's and application's responsibility to maintain the relationship in both direction. There is no magic in JPA, if you add or remove to one side of the collection, you must also add or remove from the other side, see object corruption. Technically the database will be updated correctly if you only add/remove from the owning side of the relationship, but then your object model will be out of synch, which can cause issues.
see here: https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany

Identifier Generation Exception

I have some problems with identifier generation. I use MySQL database. So, I have two entities:
#Entity
#Table(name = "users", catalog = "test1")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id", unique=true, nullable=false, updatable=false)
private Long id;
private String username;
private String password;
private boolean enabled;
#JsonBackReference
private Set<UserRole> userRole = new HashSet<UserRole>(0);
#OneToOne(cascade={CascadeType.ALL}, fetch = FetchType.LAZY, targetEntity = Utilisateur.class)
#JoinColumn(name="userUtilisateur")
#JsonManagedReference
private Utilisateur userUtilisateur;
/*.. getters and setters..*/ }
and
#Entity
#Table(name="utilisateur")
public class Utilisateur {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "firstName")
private String firstName;
#Column(name = "lastName")
private String lastName;
private String fullName;
#Column(name = "age")
private int age;
#OneToMany(mappedBy="utilisateur", targetEntity = Ticket.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JsonBackReference
private Set<Ticket> tickets = new HashSet<Ticket>(0);
#OneToMany(mappedBy="utilisateur", targetEntity=UserAssignProject.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JsonBackReference
private Set<UserAssignProject> userAssignProjects = new HashSet<UserAssignProject>(0);
#OneToMany(mappedBy="utilisateur", targetEntity=Message.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JsonBackReference
private Set<Message> messages = new HashSet<Message>(0);
/*.. getters and setters..*/ }
I have this method in UserDaoImpl:
public void save(User user) {
Utilisateur utilisateur = new Utilisateur();
user.setId(user.getId());
user.setUsername(user.getUsername());
user.setPassword(user.getPassword());
user.setEnabled(true);
user.setUserUtilisateur(utilisateur);
getCurrentSession().save(user);
}
Results:
Exception here
I've tried to use sequence, GenerationType.AUTO..., but it's not working.
Any solutions?
Thanks for your attention!

Categories