2016-06-01 2 views
0

У меня есть таблица студентов в БД, которая имеет имя, тему и метки в ней. 1 студент может иметь несколько записей для разных предметов в этой таблице.Как следует использовать синхронизацию в случае строк?

У меня есть студенческий класс DAO, который имеет метод обновления, как это:

public marks updateStudent(String name, String subject, int marks){ 
//this method first check if the record of this name and subject is there in DB 
    if(getStudentRecordFromDB(name, subject){ 
     //then return marks for this student 

    }else{ 
     //insert the record in DB and return marks 
     insertRecord(name, subject, marks); 

    } 

} 

Этот метод может быть вызван несколькими потоками одновременно для же именем студента и предмета. Я хочу, чтобы он синхронизировался только в том случае, если несколько потоков обновили одно и то же имя и тему. Итак, я подумал о синхронизации этого метода в строке имени + субъекта, но поскольку это плохая практика, также не дающая мне guranteed результаты из-за строкового константного пула (наличие этой строки в нем), я хочу использовать некоторое лучшее решение. Я не хочу синхронизировать с DAO.class, поскольку хочу синхронизацию только в случае обновления одного и того же файла. Какой должен быть лучший способ сделать это?

+0

Вам не нужно синхронизировать обновления БД - зачем вы это хотите? –

+0

На стороне БД нет ограничений, чтобы вставить несколько записей для того же имени и темы. И, к сожалению, я ничего не могу изменить в БД. Поэтому мне нужно синхронизировать его только в моем java-сервисе. Я знаю, что это может быть плохой дизайн, но я не могу с этим поделать, и я хочу, чтобы это решение работало только с Java-кода. –

+4

Здесь вы хотите использовать транзакции базы данных, и вы хотите заблокировать запись для обновления в методе 'getStudentRecordFromDB' (или использовать оптимистичную блокировку). Хотя технически возможно синхронизировать в String (используйте метод String.intern перед синхронизацией, чтобы получить уникальный экземпляр), он не защищает вас от другого приложения, работающего в той же базе данных, или против развертывания кластера, где несколько экземпляров вашего приложение запущено. –

ответ

1

Этот метод может вызываться несколькими потоками одновременно для одного и того же имени и предмета студента.

Одним из способов сделать это было бы создание уникального ограничения для вашей базы данных, которое генерирует исключение, если в базе данных уже есть комбинация студента-имени/темы. Таким образом, вы бы:

  1. запрос на имя-студента/субъектным
  2. , если он не существует, попробуйте вставить его в базу данных
  3. , если это не удается, то сделать запрос снова, чтобы защитить против гонки состояние.
  4. , если он еще не существует, то бросьте за исключением базы данных

Вы могли бы сделать это с помощью синхронизации, хотя это не является тривиальным. Вы могли бы сделать что-то вроде:

  1. Создайте объект, который облегает имя-студент/субъекта, где hashcode() и equals() использовать эти поля.
  2. Используйте ConcurrentHashMap и putIfAbsent(...)StudentNameSubject всякий раз, когда вы отправляетесь на работу. Значение может быть просто случайным постоянным объектом, так как вы не можете использовать null, и нет ConcurrentHashSet.
  3. Синхронизировать затем либо с созданным вами StudentNameSubject, либо с карточкой, если она уже существует.
  4. Выполняйте операции с базой данных внутри блока synchronized.
  5. Вы можете удалить запись с карты после заполнения блока synchronized.
Смежные вопросы