Как вставить запись в базу данных с помощью Spring jpa, когда нет конфликта - PullRequest
4 голосов
/ 26 марта 2019

У меня есть приложение весенней загрузки, которое связано с базой данных PostgreSQL с помощью spring-data-jpa, вот моя сущность с почти 40 полями

Теперь для сохранения сущности в базе данных я просто использую метод studentRepository.save

studentRepository.save(new StudentEntity());

Организация DAO

  @Table
  @Entity
  public class StudentEntity {

     @Id
     @Generate( using database sequenece)
     private long studentId;

     private String studentName;

     private String dept;

     private String age;
      ..
      ..
      }

Репозиторий

 public interface StudentRepository implements JPARepository<Long, Student> {
   }

Но теперь у меня есть требование: если в таблице есть записи о студентах с name и dept, мне не следует вставлять новую запись, я знаю, что для этого я могу использовать PostgreSQL ON CONFLICT с собственным запросом, но если Я использую собственный запрос, я должен указать все 40 полей в запросе и в качестве аргументов метода, который выглядит ужасно.

Есть ли способ сделать это проще?

Пример собственного запроса

@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);

Ответы [ 4 ]

6 голосов
/ 24 апреля 2019

Использовать базу данных.Создайте уникальное ограничение на 2 полях, и попытка добавить несколько из них будет предотвращена.

Что-то вроде

ALTER TABLE StudentEntity ADD CONSTRAINT UQ_NAME_DEPT UNIQUE (studentName,dept);

Это уникальное ограничение предотвратит вставку дубликатов комбинаций.

Вы также можете определить ограничение для вашего объекта JPA, чтобы автоматически создать индекс для тестирования

@Table(uniqueConstraints=@UniqueConstraint(columnNames = {"studentName", "dept"})
1 голос
/ 24 апреля 2019

Нет необходимости в собственном запросе. Вы можете сделать это, написав объектно-ориентированные запросы тоже. Сначала проверьте, есть ли какие-либо записи в таблице по name и dept. Если он возвращает ноль, сохраните.

StudentRepository.java

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);

}

StudentService.java

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");
}
0 голосов
/ 26 апреля 2019

Вы можете использовать легкий запрос, чтобы проверить, существует ли уже студент с таким же именем и факультетом

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);
0 голосов
/ 24 апреля 2019

Если вашим приоритетом является уменьшение многословности, поскольку это собственный SQL, вы можете избегать имен полей, если вы расположите их в правильном порядке, но вы должны поместить все значения таблицы, даже нуль:

@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);

Или вместо выполнения встроенной вставки вы можете сохранить, если метод findByStudentNameAndDebt (studentName, dept) не возвращает никакого результата.В StudentRepository (здесь родной не нужен):

@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);

А в вашем сервисе:

if(studentRepository.findByStudentNameAndDebt(studentName, dept)==null) {
   studentRepository.save(new StudentEntity());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...