Спящий режим: как в общем случае искать запись БД, которая соответствует заданному POJO во всех полях, кроме идентификатора? (ПРИМЕЧАНИЕ: поля поиска являются динамическими во время выполнения!)

Есть ли в спящем режиме простой и прямой способ поиска записи, которая соответствует заданному POJO во всех полях, кроме идентификатора?

Мне нужен подход, который не требует от меня жесткого кодирования имен полей, потому что этот метод будет использоваться несколькими таблицами/сущностями и типами POJO.

По сути, у меня есть общий Dao для абстрактного класса Pojo:

          // each Entity/POJO class is a subtype of this, with additional fields
@MappedSuperclass
public abstract class Pojo {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO, generator="native")
    @GenericGenerator(name = "native",strategy = "native")
    @JsonIgnore
    private int id;

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

      public class Dao<POJO extends Pojo> {
    private final Class<POJO> pojoClass;

    public Dao(final Class<POJO> pojoClass) {
        this.pojoClass = pojoClass;
    }

    private Session getSession() {
        return sessionFactory.openSession();
    }

    // ... standard CRUD methods go here ...

    /*  IF I have a map of all of the property names and values, I can dynamically generate a search...
     *  ...but how would I get the field names and getters from Hibernate?
     *  And more importantly... shouldn't there be a way to just pass the POJO to hibernate
     *  and tell it to find a matching a record in the appropriate entity class?
     */
    public List<POJO> findByPropertyEqual(Map<String, Object> propertyMap) {
        Session session = getSession();
        CriteriaBuilder builder = session.getCriteriaBuilder();
        CriteriaQuery<POJO> query = builder.createQuery(pojoClass);
        Root<POJO> root = query.from(pojoClass);
        List<Predicate> predicates = new ArrayList<Predicate>();
        for (Map.Entry entry: propertyMap.entrySet()) {
            predicates.add(builder.equal(root.get((String) entry.getKey()), entry.getValue()));
        }
        query.select(root).where(builder.and(predicates.toArray(new Predicate[predicates.size()])));

        List<POJO> list = session.createQuery(query).getResultList();
        session.close();
        return list;
    }
}

Причина, по которой мне это нужно: в рамках десериализации для вложенных объектов JSON мне нужно найти, существует ли уже запись, которая соответствует данной записи, и использовать ее вместо создания другой идентичной записи. В некоторых случаях эти объекты имеют идентификатор, фактически назначенный API - в этих случаях я переопределяю @JsonIgnore и могу получить из Hibernate по идентификатору... легко - НО в других случаях это просто сгенерированный идентификатор, используемый только в мой локальный сервер, и я должен искать запись по ее фактическому содержанию данных.

Например:

      {
  "name": "Outer JSON object",
  "someData": 12345,
  "innerObjects": [
    {
      "field1": "value1",
      "field2": "value2",
      "etc": "find me, I'm already in the DB!"
    },
    {
      "field1": "a different value1",
      "field2": "value2"
      "etc": "find me, I'm already in the DB!"
    }
  ]
}

Существует множество различных типов «внутренних объектов», каждый из которых будет представлен конкретной реализацией абстрактного класса Pojo. Эти внутренние объекты согласуются с точки зрения того, какая структура данных возвращается с каким полем внешнего объекта. Для некоторых полей они представлены как массив объектов, иногда как отдельные объекты, но всегда согласованным образом для каждого поля. Однако таких разных типов данных так много, что было бы невероятно утомительно жестко запрограммировать отдельный Dao для каждого из этих внутренних классов в дополнение к классу Pojo, который мне уже пришлось создать и аннотировать, и SQL ' CREATE TABLE», который должен быть написан, чтобы соответствовать ему.

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

Как правильно поступить в этой ситуации?

0 ответов

Другие вопросы по тегам