i'm triying user this code
public interface UserRepository extends CrudRepository<Usuario, Long> {
#Query("select p from User p where name = ?1")
public boolean findExistByname(String name);
#Query("select p from User p where email = ?1")
public boolean findExistByEmail(String email);
}
to check if the user in the database exists, but when not, it returns null and an error, I just don't know how to do this
You need to select a boolean value.
#Query("select count(p) = 1 from User p where name = ?1")
public boolean findExistByname(String name);
Try following code:
#Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> {
Optional<UserEntity> findByName(final String name);
}
and then check whether user exists:
userRepository.findByName("username goes here")
.orElseThrow(() -> new SecurityException("User not found in database"));
or:
userRepository.findByName("username goes here").isPresent()
Related
I want to make soft deleting by adding the additional column delete=true instead of real user deleting from database.
I have the following method in UserServiceImpl:
#Override
public void deleteUser(String id) {
UserEntity userEntity = userRepository.findById(Integer.valueOf(id))
.orElseThrow(() -> new UserNotFoundException("Id not found"));
if (userEntity.getLastAccessDate() == null) {
throw new ProhibitedScimTypeException("Broken policy");
}
userRepository.delete(userEntity);
}
In UserController I have:
#ApiResponses(value = {
#ApiResponse(responseCode = "204", content = {#Content(schema = #Schema(implementation = UserResource.class))}, description = "Successful")
})
#DeleteMapping("/Users/{id}")
public ResponseEntity<String> deleteUser(#PathVariable("id") String id) {
userService.deleteUser(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
And in UserRepository I've added the following method:
#Query("update UserEntity u set deleted = true where u = :u")
void delete(UserEntity userEntity);
Without this method in repository it didn't set true in deleted but using void delete I catch the mistake Using named parameters for method not found in annotated query 'update user set deleted = true where user = :user'.
Could you give me the piece of advice - what is the correct way to make this soft deleted?
Your reference to the parameter userEntity in your #Query is incorrect. It should be:
#Query("update UserEntity u set deleted = true where u = :userEntity")
Repository Class:
#Repository // This my architecture repository class.
public class UserRepositoryImp implements UserRepository {
private EntityManager entityManager;
#Autowired
public UserRepositoryImp(EntityManager entityManager) {
this.entityManager = entityManager;
}
private static final String MY_SQL_COUNT_EMAIL =
"SELECT count(e) FROM User e WHERE e.email=:email "; // This is hibernate query.
#Override
public Integer getCountByEmail(String email) {
Session session = entityManager.unwrap(Session.class);
TypedQuery<Integer> query = session.createQuery(MY_SQL_COUNT_EMAIL, null);
query.setParameter("email", email); // This is return count in database check database
// .. if you email this database passing already exist this email but your count zero created new email.
return query.executeUpdate();
}
}
Service Class:
#Service
#Transactional
public class UserServiceImp implements UserService {
#Autowired
UserRepository userRepository;
#Override
public User validateUser(String email, String password) throws EtAuthException {
return null;
}
#Override
public User registerUser(User user) throws EtAuthException {
Pattern pattern = Pattern.compile("^[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2, 6} $ "); // This regex.
if (pattern.matcher(user.getEmail()).matches()) {
throw new EtAuthException("Invalid email format"); // This is check email regex.
}
Integer count = userRepository.getCountByEmail(user.getEmail()); // This is my method
// .. count email in database and repository methods
if (count > 0) {
throw new EtAuthException("Email already in use");
}
Integer userId = userRepository.create(user);
return userRepository.findById(userId);
}
}
Postman Error:
Cannot invoke "java.lang.Class.isAssignableFrom(java.lang.Class)"
because "resultClass" is null"
Problem:
My problem is actually. I want to write a query to hibernated but for some reason it doesn't work. For such operations in spring boot, ie typing a query, for example polling email, put delete add and updated, how do I do it? I need to query me. I can't solve this problem.
You are calling executeUpdate() for a select query. Try using getSingleResult() instead.
#Override
public long getCountByEmail(String email) {
Session session = entityManager.unwrap(Session.class);
String query = "SELECT count(e) FROM User e WHERE e.email = :email";
TypedQuery<Long> typedQuery = session.createQuery(query, Long.class);
typedQuery.setParameter("email", email);
return typedQuery.getSingleResult();
}
OR
#Override
public long getCountByEmail(String email) {
String query = "SELECT count(e) FROM User e WHERE e.email = :email";
TypedQuery<Long> typedQuery = entityManager.createQuery(query, Long.class);
typedQuery.setParameter("email", email);
return typedQuery.getSingleResult();
}
I have the following code:
public interface UserRepository extends CrudRepository<User, Integer> {
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (?,?,?)", nativeQuery = true)
void insertUserToUsers(String email, String password, String name);
}
I don't want to pass the values, i want to pass a user object like this:
void insertUserToUsers(User user);
Try this
public interface UserRepository extends CrudRepository<User, Integer> {
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (:#{#user.email},:#{#user.firstname},:#{#user.name})", nativeQuery = true)
void insertUserToUsers(#Param("user") User user);
}
Try this code,
#Modifying
#Transactional
#Query(value = "INSERT INTO users(email, password, name) VALUES (?,?,?)", nativeQuery = true)
void insertUserToUsers(String email, String password, String name);
default void insertUserToUsers(User user) {
return insertUserToUsers(user.getEmail(), user.getPassword(), user.getName());
}
Where you use your UserRepository you can use the default method to save user:
ex:
#Service
public class MyService{
#Autowired
private UserRepository userRepository ;
public void example(User user){
userRepository.save(user)
}
}
Because CrudRepository give us some default methods , you can check here
Suppose I have a bidirectional 1-1 association with the Person entity
#Entity
public class Person {
#OneToOne(optional=false)
#JoinColumn(name = "contact_id")
private Contact contact;
// getters/setters/constructors
}
And the Contact Entity
#Entity
public class Contact {
#OneToOne(mappedBy="contact")
private Person person;
// getters/setters/
}
I couldn't find a way to select parent object for Person Entity using the Contact entity. Like so...
criteriaQuery.select(root.get(Contact_.person));
I get this error:
Incompatible types. Required Selection<? extends capture of ?> but 'get' was inferred to Path<Y>: no instance(s) of type variable(s) exist so that Person conforms to capture of ?
Is there a way of doing this? I wanted to return a Predicate for Person Entity using the Contact root. For eg.
public static Specification<Person> phoneWithCountryCode(String countryCode) {
return new Specification<Person>() {
#Override
public Predicate toPredicate(
Root<Contact> root,
CriteriaQuery<?> criteriaQuery,
CriteriaBuilder criteriaBuilder
) {
String startsWithPattern = countryCode + "%";
criteriaQuery.select(root.get(Contact_.person));
return criteriaBuilder.like(
root.get(Contact_.phone), startsWithPattern
);
}
};
}
Yes, you can do.
I did it.I Have Relationship ( Book -- Review).
In your case create Specification<Person> and use join with contact.
like this,
Join joins = root.join("contact");
If help requires just follow my code.
public class BookSpecification {
public static Specification<Book> getBookByNameAndReviewId(){
return new Specification<Book> () {
#Override
public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb)
{
//List<javax.persistence.criteria.Predicate>
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get("name"), "spring boot"));
Join joins = root.join("reviews");
predicates.add(cb.equal(joins.get("no") , 584));
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
// return cb.equal(root, predicates);
}
};
}
}
I'm trying to see how I would create a JPA Critera query which allows for fully dynamic filtering with multiple levels.
For example
select *
from table
where (
(column1 = 'A'
and
(column2 = 'B' or column3 = 'C')
)
or
column3 = 'D'
You need to create a Specification as in the test below. This can be dynamic.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=HelloWorldConfig.class)
public class SpecificationTest {
#Autowired
private AccountRepository repository;
#Test
public void test1() {
final List<String> names = Arrays.asList(new String[]{"George","Max"});
Specification<Account> specification = new Specification<Account>() {
public Predicate toPredicate(Root<Account> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(root.get("name").in(names).not());
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
assertNotNull(repository);
repository.save(makeAccount("Greg", "123456787", "01-02-01"));
repository.save(makeAccount("George", "123456788", "01-02-02"));
repository.save(makeAccount("Max", "123456789", "01-02-03"));
List<Account> accounts = repository.findAll(specification);
assertEquals(1,accounts.size());
assertEquals("123456787",accounts.get(0).getAccountNumber());
}
private Account makeAccount(String name, String accountNumber, String sortCode) {
Account account = new Account();
account.setName(name);
account.setAccountNumber(accountNumber);
account.setSort(sortCode);
return account;
}
}
Where the repository looks like :
#Repository
public interface AccountRepository extends JpaRepository<Account, Long>, JpaSpecificationExecutor<Account> {
}