I can't get a row from a database in hibernate with sessionFactory.getCurrentSession().load (...) - spring

I have a database (in postgres) and I'm working with spring 3 and hibernate 3, the problem is when try to delete or get a row from database, here is the class that I'm using, ohh another thing after the query, a don't have any mistake, the only thing es that class User is null
#Repository("userDao")
public class UserDao implements IUserDao {
#Autowired
private SessionFactory sessionFactory;
public void SaveUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
#SuppressWarnings("unchecked")
public List<User> ListUsers() {
List<User> users = (List<User>) sessionFactory.getCurrentSession().createCriteria(User.class).list();
return users;
}
public User GetUserById(Integer id) {
User user = (User) sessionFactory.getCurrentSession().load(User.class, id);
return user;
}
}
by the way, methods, SaveUser and ListUser work really good.
this is the model class
#Entity
#Table(name = "mrbean")
public class User {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
#Column (name = "id")
private Integer id;
#NotNull (message = "not null")
#NotEmpty (message = "empty")
#Column (name = "user_name", length = 20, nullable = false, unique = true)
private String userName;
#NotNull
#NotEmpty (message = "empty password")
#Size (min = 7, max = 20, message = "La contraseƱa debe tener entre 7 y 20 caracteres")
#Column (name = "password", length = 20, nullable = false)
private String password;
//with getters and setters
this is what hibernate show in console when
User user = (User)sessionFactory.getCurrentSession().load(User.class, id) is executed
Hibernate: select user0_.id as id0_0_, user0_.password as password0_0_, user0_.user_name as user3_0_0_ from mrbean user0_ where user0_.id=?

I would use "get" instead of "load" because load() creates a proxy of User (see Hibernate ref doc )
so i would try : User user = (User) sessionFactory.getCurrentSession().get(User.class, id);

Related

JPA Failing to produce a proper SQL query when a parameter has a composite primary key

Today I came across a weird bug while trying to test a JPA update query and I'm wondering if this a SpringBoot bug.
I have the following entities
An Entry entity
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
public class Entry {
#Id
private String id;
#ManyToOne(targetEntity = User.class)
#JoinColumn(referencedColumnName = "username")
#NotNull
private final User username;
#Enumerated(EnumType.STRING)
#NotNull
private Type type;
#ManyToOne(targetEntity = Category.class)
#JoinColumns({#JoinColumn(referencedColumnName = "name"),#JoinColumn(referencedColumnName = "type"),#JoinColumn(referencedColumnName = "username")})
#NotNull
private Category category;
#Size(max = 45)
#NotBlank
private String description;
#NotNull
private Double amount;
#NotNull
private final Date createdAt;
private Timestamp lastUpdate;
#NotNull
private Boolean isDeleted;
public enum Type{
Income,Expense
}
}
A Category entity with a composite key
#Entity
#NoArgsConstructor(access = AccessLevel.PROTECTED, force = true)
#Setter
#Getter
#EqualsAndHashCode(of = {"id"})
#ToString(of = {"id"})
public class Category {
#EmbeddedId
private CategoryId id;
private final Timestamp createdAt = Timestamp.from(Instant.now());
#ManyToOne(targetEntity = User.class)
#JoinColumn(referencedColumnName = "username")
private final User user;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "category")
private List<Entry> entries;
public Category(String name, Type type, User user){
this.id = new CategoryId(name,type,user.getUsername());
this.user = user;
}
}
A CategoryID that is the embeddable composite key of the Category entity
#Data
#Embeddable
#AllArgsConstructor
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#EqualsAndHashCode(of = {"name","type","username"})
public class CategoryId implements Serializable {
private String name;
#Enumerated(EnumType.STRING)
private Type type;
private String username;
}
The following repository
#Repository
public interface EntryRepository extends JpaRepository<Entry, String> {
Optional<Entry> findEntryById(String id);
#Modifying(clearAutomatically = true, flushAutomatically = true)
#Query(value = "UPDATE Entry e SET e.username = :username, e.type = :type, e.category = :category, e.description = :description, e.amount = :amount, e.createdAt = :date, e.lastUpdate = :lastUpdate, e.isDeleted = :isDeleted WHERE e.id = :id")
void update(#Param("id") String id,
#Param("username") User username,
#Param("type") Entry.Type type,
#Param("category") Category category,
#Param("description") String description,
#Param("amount") Double amount,
#Param("date") Date date,
#Param("lastUpdate") Timestamp lastUpdate,
#Param("isDeleted") Boolean isDeleted);
}
And finally the following Unit Test
#Test
void update() {
//given
User testUser = userRepository.save(new User("testUser#test.com","000000000000000000000000000000000000000000000000000000000000"));
Category testCategory = categoryRepository.save(new Category("Test Category", Entry.Type.Income,testUser));
Entry testEntry = new Entry("testEntry",testUser, Entry.Type.Income,
testCategory, "test",
0.0, new Date(343), from(now()), false);
System.out.println(testCategory);
entryRepositoryUnderTest.save(testEntry);
//when
entryRepositoryUnderTest.update("testEntry",testUser,Expense,testCategory,"testUpdated",1.0,new Date(346), from(now()),true);
Optional<Entry> actual = entryRepositoryUnderTest.findEntryById("testEntry");
System.out.println(actual.get().getCategory());
//then
assertThat(actual.get().getUsername()).isEqualTo(testUser);
assertThat(actual.get().getType()).isEqualTo(Expense);
assertThat(actual.get().getCategory()).isEqualTo(testCategory);
assertThat(actual.get().getDescription()).isEqualTo("testUpdated");
assertThat(actual.get().getAmount()).isEqualTo(1.0);
assertThat(actual.get().getIsDeleted()).isEqualTo(true);
}
When I run the test it fails and I get the following error message:
could not execute update query; SQL [update entry set username_username=?, type=?,category_name=?=category_type=?, description=?, amount=?, created_at=?, last_update=?, is_deleted=? where id=?]; nested exception is org.hibernate.exception.DataException: could not execute update query
As you can see here when SpringBoot is trying to produce a SQL query statement from my #Query parameter it can not properly extract the Category field from the parameters and inject it's composite embeddable key into the SQL statement. It has no problem extracting the User parameter because the User is an entity with an id that is not composite.
Is this a SpringBoot bug or am I missing something?
EDIT:
This is the structure of the database

Spring boot JPA many to many with extra column insert and update issue

Here is my initial question.
Spring Data JPA Many to Many with extra column User and Roles
Now I have the right tables created, but can't make it work for the update.
Here is the code:
User.java
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
#OneToMany(mappedBy="user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private List<UserRole> roles;
// getters and setters
}
Role.java
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// getters and setters
}
UserRole.java
#Entity
#Table(name = "users_to_role")
public class UserRole implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#Id
#ManyToOne
#JoinColumn(name = "role_id")
private Role role;
private Date createdAt;
public UserRole(){}
public UserRole(User user, Role role, Date date) {
this.user = user;
this.role = role;
this.createdAt = date;
}
// getters and setters
}
Controller
#RestController
public class APIController {
#Autowired
RoleRepository roleRepository;
#Autowired
UserRepository userRepository;
#ResponseBody
#RequestMapping(value = "create", method = RequestMethod.GET)
public String create(){
//Insert test - WORKING BUT NOT SURE IF ITS RIGHT WAY
List<UserRole> userRoles = new ArrayList<>();
Role role = roleRepository.getOne((long) 1);
//Create user
User user = new User();
user.setUsername("test");
//Create userRole
userRoles.add(new UserRole(user, role, new Date()));
user.setRoles(userRoles);
userRepository.save(user);
return "created";
}
#ResponseBody
#RequestMapping(value = "edit", method = RequestMethod.GET)
public String edit(){
//Edit test - NOT working
List<UserRole> userRoles = new ArrayList<>();
Role role = roleRepository.getOne((long) 2);
//get user from db
User user = userRepository.getOne((long) 1);
//Create userRole
userRoles.add(new UserRole(user, role, new Date()));
// WAS FIRST ATTEMPT using user.setRoles(userRoles); but got error and use
//https://stackoverflow.com/questions/9430640/a-collection-with-cascade-all-delete-orphan-was-no-longer-referenced-by-the-ow
//user.setRoles(userRoles);
user.getRoles().clear();
user.getRoles().addAll(userRoles);
userRepository.save(user);
return "done";
}
}
I am getting this error:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'user_id' cannot be null

Spring Security Set Role On Registration

I'm new to Spring security, so I've followed some tutorials but I'm having trouble understanding how the structure of roles really works under the hood. I have two tables, one for the User:
#Entity
#Table(name = "UserProfile", schema = "dbo", catalog = "DevTestTeam")
public class UserProfileEntity implements UserDetails{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private long id;
#Column(name = "enabled", nullable = false)
private boolean enabled;
#NotEmpty(message = "Enter a password.")
#Size(min = 6, max = 15, message = "Password must be between 6 and 15 characters.")
#Column(name = "password", nullable = true, length = 100)
private String password;
#NotEmpty(message = "Enter a username.")
#Size(min = 6, max = 20, message = "Username must be between 6 and 20 characters.")
#Column(name = "username", nullable = true, length = 20, unique = true)
private String username;
#OneToOne
#JoinColumn(name = "role_id")
private RoleEntity role;
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return authorities;
}
and one for the role:
#Entity
#Table(name = "Role", schema = "dbo", catalog = "DevTestTeam")
public class RoleEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private long id;
#Column(name = "name", nullable = true, length = 255)
private String name;
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;
}
My confusion comes when creating a new user. I have a registration form backed by a UserProfileEntity object, and that populates the username and password. Then obviously it's easy to setEnabled()=true (I left some of the getters/setters out of this code for clarity).
My question is how to set the role when instantiating a UserProfileEntity to be saved in the database. My role_id foreign key should just take an integer and return the role from the Role table, but I'm not sure how to express this when instantiating. I have a ROLE_USER in the roles table with an id of 1, and I feel like this is pretty simple to instantiate but I can't find the answer I'm looking for.
UserImpl:
#Service
public class UserProfileServiceImpl implements UserProfileService{
#Autowired
private UserProfileDao userDao;
#Override
public UserProfileEntity findByUser(String username) {
return userDao.findByUsername(username);
}
#Override
public List<UserProfileEntity> findAll() {
List<UserProfileEntity> list = userDao.findAll();
return list;
}
#Override
public UserProfileEntity save(UserProfileEntity persisted) {
userDao.save(persisted);
return null;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserProfileEntity user = userDao.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found.");
}
return user;
}
}
You'll need some repository method to obtain user role by name:
RoleEntity roleEntity = roleEntityRepository.findByName("ROLE_USER");
Then set that RoleEntity to UserProfileEntity before persisting it:
UserProfileEntity userProfileEntity = new UserProfileEntity();
userProfileEntity.setRoleEntity(roleEntity);
userService.save(userProfileEntity);
What you also want is to leave your UserProfileEntity unextended. For Spring Security, you'll need UserDetailsService implementation:
#Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserProfileEntity userProfileEntity = userRepository.findByUsername(username);
if (userProfileEntity == null) {
throw new UsernameNotFoundException("Non existing user!");
}
return new org.springframework.security.core.userdetails.User(userProfileEntity.getUsername(),
userProfileEntity.getPassword(),
Arrays.asList(new SimpleGrantedAuthority(userByUsername.getRoleEntity().getName())));
}
}
However, I see that your requirements are quite simple - one role per user. Therefore, your RoleEntity could simply be an enum with predefined roles:
public enum RoleEntity {
ROLE_USER
}
And in UserProfileEntity you'd use it like this:
public class UserProfileEntity {
#Enumerated(EnumType.STRING)
private RoleEntity roleEntity;
}
To persist user with role:
UserProfileEntity userProfileEntity = new UserProfileEntity();
userProfileEntity.setRoleEntity(RoleEntity.USER);
userService.save(userProfileEntity);

How to delete entity from database

i am new on hibernate-spring tirple..
i just try to code simple register book.. i have following codes:
Student.java
#Entity(name = "STUDENTS")
#NamedQueries({
#NamedQuery(name = "getAllStudent", query = "SELECT k FROM STUDENTS k ORDER BY k.id DESC"),
#NamedQuery(name = "findByName", query = "SELECT k FROM STUDENTS k WHERE k.name LIKE :name")
})
public class Student {
#Column(name = "STUDENTNO", nullable = false)
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "SURNAME")
private String surname;
#Column(name = "AGE")
private String age;
// GET ve SET metods
StduentDAO.java
#Repository
#Transactional(readOnly = true)
public class StudentDAO implements IStudentDAO {
#PersistenceContext
EntityManager em;
#Override
public void deleteStudent(Student student) {
Student temp = em.getReference(Student.class, student.getId());
em.remove(temp);
System.out.println("### getting out from studentDAO deleteStudent method ###")
StudentController.java
#Component
#Scope(value = "request")
public class StudentController {
#Autowired
IStudentDAO studentDAO;
List<Student> allStudentList = new ArrayList();
Student student = new Student();
#PostConstruct
private void loadStudents() {
allStudentList = studentDAO.allStudent();
public void deleteStudent() {
studentDAO.deleteStudent(student);
System.out.println("### getting out from StudentController deleteStudent method ### ");
}
When I run deleteStudent() codes i am getting:
"### getting out from studentDAO deleteStudent method ###"
"### getting out from StudentController deleteStudent method ### "
i see these on output but nothing is deleting from database.. i searched a bit and i found this "every entitiy manager's methods open own session." that is why it says i should write my StudentDAO's deleteStudent methof like above..
i think i am missing something about transaciton but i have not recognized yet..
what should i do about this ?
Thanks..
#Transactional annotation create a transaction on your DBMS.
If you use (readOnly = true) you prevent operation on your DB (as INSERT/UPDATE/DELETE).
Remove readOnly = true so your delete method will work.

Hibernate exception - hibernate.internal.QueryImpl cannot be cast

I'm trying to authenticate with a database username. So far the error is:
Your login attempt was not successful, try again.
Reason: org.hibernate.internal.QueryImpl cannot be cast to com.**.**.model.UserEntity
The query in the dao class
#Repository
public class UserEntityDAOImpl implements UserEntityDAO{
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
#Override
public UserEntity getUserByName(String username) {
// TODO Auto-generated method stub
UserEntity userEntity = (UserEntity)
sessionFactory.getCurrentSession().createQuery(
"select u from UserEntity u where u.username = '' + username + ''");
return userEntity;
}
service
#Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
#Autowired
private UserEntityDAO userEntityDAO;
#Autowired
private Assembler assembler;
#Override
#Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
// TODO Auto-generated method stub
UserDetails userDetails = null;
UserEntity userEntity = userEntityDAO.getUserByName(username);
if (userEntity == null)
throw new UsernameNotFoundException("user not found");
return assembler.buildUserFromUser(userEntity);
}
}
DB table that holds the user details
/*Table structure for table `user` */
CREATE TABLE `user` (
`user_id` INT(11) NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NULL DEFAULT NULL ,
`password` VARCHAR(45) NOT NULL ,
`username` VARCHAR(45) NOT NULL ,
`active` TINYINT(1) NOT NULL ,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
Model
#Entity
#Table(name = "user", schema = "")
#Component
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "user_id")
private Integer id;
#Column(name = "name")
private String name;
#Basic(optional = false)
#Column(name = "password")
private String password;
#Basic(optional = false)
#Column(name = "username")
private String username;
#Basic(optional = false)
#Column(name = "active")
private boolean active;
#JoinTable(name = "user_role", joinColumns = {
#JoinColumn(name = "user_id")}, inverseJoinColumns = {
#JoinColumn(name = "role_id")})
#OneToMany
private Set <Role> roles;
public UserEntity() {
}
//getters and setters
What I would like insight on is why there is a problem with the query, and why the username is not able to be retrieved from the database.
Edit: After changing the query, the login is still not successful. The login page is returned and there is no error message in the output console other than this:
Hibernate: select userentity0_.user_id as user1_1_, userentity0_.active as
active1_, userentity0_.name as name1_, userentity0_.password as password1_,
userentity0_.username as username1_ from user userentity0_ where
userentity0_.username=?
Hibernate: select roles0_.user_id as user1_1_1_, roles0_.role_id as role2_2_1_,
role1_.role_id as role1_0_0_, role1_.role as role0_0_ from user_role roles0_ inner
join role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=?
INFO : com.**.**.controller.ApplicationController - This is the login page {}.
You forgot to execute the query you created. It should be:
sessionFactory.getCurrentSession().createQuery(...).uniqueResult();
Also, use a proper bind variable. As it stands your query is bogus with single quotes, I'm not sure if you made a typo pasting it into stackoverflow, but something like this would be much safer:
sessionFactory
.getCurrentSession()
.createQuery("select u from UserEntity u where u.username = :username")
.setParameter("username", username)
.uniqueResult();

Resources