I have spring boot application that is connected with the PostgreSQL database using spring-data-jpa
, here is my entity with nearly 40 fields
Now for saving the entity into database, I'm just using the studentRepository.save
method
studentRepository.save(new StudentEntity());
DAO Entity
@Table
@Entity
public class StudentEntity {
@Id
@Generate( using database sequenece)
private long studentId;
private String studentName;
private String dept;
private String age;
..
..
}
Repository
public interface StudentRepository implements JPARepository<Long, Student> {
}
But now I have requirement, if there is any student record in table with name
and dept
I should not insert the new record, I know I can use PostgreSQL ON CONFLICT
with native query for this, but if I use native query I have to specify all 40 fields in query and as method arguments which looks ugly.
Is there any way to make it simpler?
Example of native query
@Query(value = "insert into Users (name, age, email, status) values (:name, :age, :email, :status)", nativeQuery = true)
void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email);
Use the database. Create a unique constraint on the 2 fields and trying to add multiple of those will be prevented.
Something like
ALTER TABLE StudentEntity ADD CONSTRAINT UQ_NAME_DEPT UNIQUE (studentName,dept);
This unique constraint will prevent the insertion of duplicate combinations.
You could also define an constraint on your JPA entity to automatically create the index for testing
@Table(uniqueConstraints=@UniqueConstraint(columnNames = {"studentName", "dept"})
No need of native query. You can do it by writing object oriented queries too. first check is there any record present in table by name
and dept
. If it returns null, then do your save.
public interface StudentRepository implements JPARepository<Long, Student> {
@Query("FROM Student AS stu WHERE lower(stu.name) = lower(:studentName) AND lower(stu.dept) = lower(:dept)")
public Student findStudentByNameAndDept(@Param("studentName") String studentName, @Param("dept") String dept);
//if you have already duplicates in your db, then you can do the followings too..
@Query("FROM Student AS stu WHERE lower(stu.name) = lower(:studentName) AND lower(stu.dept) = lower(:dept)")
public List<Student> findAllStudentsByNameAndDept(@Param("studentName") String studentName, @Param("dept") String dept);
}
if(studentRepository.findStudentByNameAndDept(name,dept)==null){
//save
}else{
//custom hanlding
throw StudentExistsException("Student with the given name/dept exists");
}
OR
//if already duplicates exisited in db
if(studentRepository.findStudentByNameAndDept(name,dept).isEmpty()){
//save
}else{
//custom hanlding
throw StudentExistsException("Student with the given name/dept exists");
}
If your priority is to reduce verbosity, as it is native sql you can avoid the names of the fields if you put them in the correct order, but you must put all the values of the table, even the null:
@Query(value = "insert into Users values (:name, :age, :email, :status)", nativeQuery = true)
void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email);
Or instead of doing it with native insert, you can save if the method findByStudentNameAndDebt(studentName, dept), does not return any result. In StudentRepository (here native is not necessary):
@Query("SELECT a FROM Student as a WHERE lower(a.studentName) = lower(:studentName) AND lower(a.dept) = lower(:dept)")
public Student findByStudentNameAndDebt(@Param("studentName") final String studentName, @Param("dept") final String dept);
And in your service:
if(studentRepository.findByStudentNameAndDebt(studentName, dept)==null) {
studentRepository.save(new StudentEntity());
}
you can use a lightweight query to check whether a student with same name and department already exists
public interface StudentRepository implements JPARepository<Long, Student> {
@Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Student s WHERE s.studentName= :studentName AND s.dept= :dept")
public boolean existsByNameAndDepartment(@Param("studentName") String studentName, @Param("dept") String dept);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.