Форум программистов, компьютерный форум, киберфорум
Наши страницы
Java: Базы данных
Войти
Регистрация
Восстановить пароль
 
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
1

Одна таблица, несколько сущностей

18.06.2018, 14:46. Просмотров 242. Ответов 11

Добрый день, уважаемые коллеги!

Подскажи пожалуйста, как бы Вы сделали? Есть бэк на Java 8, Spring Boot, JpaRepository. Есть таблица, со старого приложения 38 полей, все данные в одной строке относиться к одному событию, есть 5 разных отделов, каждый должен видеть какую то часть данных, причем перекрестно один свою часть, другой половину этой же части + еще свои пару полей и т.п. (На самом деле отделов больше).
Хотел декомпозировать написать модель под каждый отдел и указать аннотацией @Table(name = "data") ссылку на одну таблицу, но что то мне подсказывает что так плохо делать. А если я записываю данные через POST запрос и в теле опускаю часть полей, то JpaRepository пишет в базу null затирая данные этого поля, несмотря на то, что в свойствах ORM стоит стратегия update. Как поступить, подскажи, пожалуйста? Написать кучу методов в контроллере индивидуально по выгрузке данных и записи своих полей для каждого отдела? Тогда что делать с "затиранием"? Разбивать данные и делать миграцию данных по таблицам тоже крайне не хотелось бы, потому что одна строка - одно связное событие обработанное разными отделами, отделы могут прибавиться, а поля больше расширяться не будут в этой таблице.

Добавлено через 18 минут
Что приходит в голову, так отказаться от ORM в данном случае или писать прямые запросы SELECT и те, те столбцы. И по записи так же, написать кучу методов и отпамить в контроллере для каждого отдела
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.06.2018, 14:46
Ответы с готовыми решениями:

зависимости сущностей
всем привет! ребят нашел задачу как пример на джуниора, в ней цель:...

Класс сущностей из базы данных
Не видно ни одной таблицы, они там есть, как решить проблему?

Аннотация @Version для сущностей (Entity)
В книге по spring написано что для того чтобы Hibernate разбирался с различными...

Реализация DAO для нескольких сущностей
Доброго времени суток! Вопрос быть может банальный, но... Имеется некоторый...

Функции классов сущностей equals и hashCode формируемые Hibernate
Доброго времени суток! Ребят скажите для чего Hibernate в классах сущностях...

11
KEKCoGEN
Эксперт Java
2054 / 1927 / 498
Регистрация: 28.12.2010
Сообщений: 7,716
18.06.2018, 18:00 2
TurboDuck, вопрос какие кейсы нужно поддерживать и как предполагается развивать код. Если предполагается что отделы будут добавлятся динамически это одно решение. Если есть 5 отделов и в ближайший год может быть добавят ещё два, то дешевле будет использовать другой подход.

Представим что отделов 5 и добавлять их ненадо.

Модель можно оставить одну.
Для каждого отдела нужно сделать DTO который будет передаваться клиенту и приходить с клиента. В DTO прописаны поля которые видит отдел.
В зависимости от принадлежности юзера к отделу, энтити нужно мапить в соотв. дто и дальше работать с ним (логику маппинга опять таки можно реализовать многими способами)

Насчет апдейта все просто. Должна помочь аннотация @DynamicUpdate на классе энтити

Есть куда более гибкие методы решения. Например череж Json View или через фильтры. Вопрос нужно ли это в данном случае.
1
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
19.06.2018, 06:10  [ТС] 3
Спасибо! Да вариант, второй что добавляться сильно не будут, может один два. Вопрос в том, что у них перекрестные задачи (и как следствие поля в таблице), а JpaRepository при передаче в теле POST не всех полей от модели, остальные затирает null'ом, а ответ не могу найти как сделать, что бы он обновлял только переданные, а остальные не трогал.

Сейчас почитаю про @DynamicUpdate, благодарю!
0
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
19.06.2018, 06:59  [ТС] 4
Возможно проблема, в том что база MySQL и по умолчанию стоит значение "default null", аннотации ни @DynamicUpdate, ни @SelectBeforeUpdate не помогли. Использовал только Spring Boot Jpa Repository, добавил в pom.xml зависимость на Hibernate 5.0.1 Final и аннотации. Результат тот же. Выглядит это так, не передал в теле запроса код аэропорта (хотя он был там UAAA указан), сделал update только имени аэропорта (цифру 2 в конец поставил) и получил в результате null в базе вместо бывшего там кода.
0
Миниатюры
Одна таблица, несколько сущностей  
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
19.06.2018, 07:54  [ТС] 5
Model
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Entity
@SelectBeforeUpdate
@DynamicUpdate
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Airports {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
 
    private String airport;
 
    private String code;
 
    public Airports() {
    }
 
    public Airports(long id, String airport, String code) {
        this.id = id;
        this.airport = airport;
        this.code = code;
    }
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getAirport() {
        return airport;
    }
 
    public void setAirport(String airport) {
        this.airport = airport;
    }
 
    public String getCode() {
        return code;
    }
 
    public void setCode(String code) {
        this.code = code;
    }
 
    @Override
    public String toString() {
        return "Airports{" +
                "id=" + id +
                ", airport='" + airport + '\'' +
                ", code='" + code + '\'' +
                '}';
    }
Добавлено через 1 минуту
Вырезка из Controller
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RestController
public class AirportsController {
    private AirportsRepository repository;
 
    public AirportsController(AirportsRepository repository) {
        this.repository = repository;
    }
 
    @GetMapping("airports/all")
    public Collection<Airports> getAllAirports() {
        return repository.findAll();
    }
 
......
    
 
    @PostMapping(value = "airports/update")
    public ResponseEntity updateAirportById(@RequestBody Airports airports) {
        Airports foundedById = repository.findOne(airports.getId());
        foundedById.setAirport(airports.getAirport());
        foundedById.setCode(airports.getCode());
        repository.save(foundedById);
 
        return new ResponseEntity(foundedById, HttpStatus.OK);
    }
Добавлено через 2 минуты
Конечно я могу ветвление if else написать, что если code не передан, то не делать set для этого поля объекта, но ведь это как то не правильно, так проверять все поля? Ладно тут 3 поля справочник: айди+ название + код...

Добавлено через 27 минут
Попробовал несколько моделей на одну таблицу, все работает отлично, только очень много лишнего кода будет. Аннотацией @Table(name = "") привязал к одной таблице. Если на неполной модели делать апдейт, то поля на null, которых не было указано в модели не перетираются на null

Добавлено через 20 минут
Как вариант, конечно написать много методов с нативными запросами, такое 100% прокатит
0
KEKCoGEN
Эксперт Java
2054 / 1927 / 498
Регистрация: 28.12.2010
Сообщений: 7,716
19.06.2018, 07:56 6
TurboDuck, отдавать модель клиенту плохо. Нужно отдавать DTO. Логикой должен заниматься сервис а не контроллер. На метод сервиса нужно повесить аннотацию @Ttransactional. Чтобы увидеть в чем проблема с затиранием нужно включить печать SQL в лог и убрать лишние аннотации. Код хреновый короче...

Предыдущий пост не читал чтоли?
1
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
19.06.2018, 10:19  [ТС] 7
Тикет на спринге по этому поводу, https://jira.spring.io/browse/DATAJPA-209
Читал, я понял. Говорю протестировал (впервые), что так можно сделать. Спасибо. DTO - шаблон же проектирования, для снижения нагрузки, что бы не кидать кучу запросов к базе, а собрать данные в один объект и передать одним разом. Подскажите, пожалуйста, в чем тут разница и примерно как сделать? Несколько моделей к одной таблице, выполняют ту же функцию. Заранее благодарю!

Добавлено через 1 час 12 минут
Нашел решение, простая проверка, не обновит данные ранее найденные в БД, поэтому все отлично отработает. Проверил уже
Java
1
2
if(airports.getAirport() != null) 
  foundedById.setAirport(airports.getAirport());
0
KEKCoGEN
Эксперт Java
2054 / 1927 / 498
Регистрация: 28.12.2010
Сообщений: 7,716
19.06.2018, 18:05 8
Цитата Сообщение от TurboDuck Посмотреть сообщение
DTO - шаблон же проектирования
нет, DTO - Data Transfer Object. Из моего ответа ты походу не понял ничего. Делай как хочешь...будет работать и ладно. Не думаю что от тебя чего то большего ждут.

Цитата Сообщение от TurboDuck Посмотреть сообщение
Тикет на спринге по этому поводу
этот тикет к твой проблеме никакого отношение не имеет.
0
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
20.06.2018, 06:17  [ТС] 9
Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения. Data Transfer Object, в отличие от business object или data access object не должен содержать какого-либо поведения. (c) Wikipedia

Добавлено через 3 минуты
Смысл я понял, что там должны быть только поля у класса, для передачи в БД одним объектом и не должно быть ни какой логики поведения. Но по сути в модели у меня это же самое и есть, там приватные поля и ацессоры для связки Спрингом, я же не пишу на чистой Java ООП приложение, не использую композицию или наследование, поэтому вопрос тот же, а в чем тогда разница, условия же соблюдаются?
0
xoraxax
1340 / 1282 / 378
Регистрация: 05.07.2013
Сообщений: 6,155
Завершенные тесты: 1
20.06.2018, 07:43 10
Разница в том, что рано или поздно ты словишь какой нибудь lazy init exception, например
1
TurboDuck
42 / 41 / 13
Регистрация: 23.11.2015
Сообщений: 387
20.06.2018, 10:25  [ТС] 11
Насколько я понял, @Entity каждый раз будет делать update таблицы при запуске под каждую модель привязанную к этой таблице, а это нам не надо, а DTO просто объект для разового запроса к БД всем скопом, который не будет производить ни каких действий по обновлению таблиц, поэтому надо юзать его.

Спасибо ребят
0
KEKCoGEN
Эксперт Java
2054 / 1927 / 498
Регистрация: 28.12.2010
Сообщений: 7,716
20.06.2018, 15:18 12
Цитата Сообщение от TurboDuck Посмотреть сообщение
DTO просто объект для разового запроса к БД
нет. DTO это просто класс. Ничего более
0
20.06.2018, 15:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.06.2018, 15:18

Влияет ли на быстродействие EntityManager количество классов сущностей в persistence-unit
Влияет ли на быстродействие EntityManager количество классов сущностей в...

Одна таблица или несколько со связью один к одному
Здравствуйте. У меня такой вопрос. Допустим нужно создать таблицу с данными о...

Выяснить, имеется ли у него одна самая короткая строка или таких строк несколько. Вывести одна или не одна.
дaн текстовый файл с произвольным именем. Выяснить, имеется ли у него одна...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru