I have this method on my Dao class:
public List<E> search(String key, Object value) { EntityManager entityManager = getEntityManager(); entityManager.getTransaction().begin(); List result = entityManager.createQuery("SELECT a FROM "+clazz.getSimpleName()+" a WHERE a."+key+" LIKE '"+value+"%'").getResultList(); entityManager.getTransaction().commit(); entityManager.close(); return result; }
the sql works fine when the attribute is @Column
or a @OneToOne`, but when it’s something like that:
@OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL) @OrderColumn private List<Titulo> nome;
where the class Titulo
has this attributes:
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; @Column private String idioma; @Column(length=32) private String conteudo;
causes this error:
message: left and right hand sides of a binary logic operator were incompatible [java.util.List(org.loja.model.categoria.Categoria.nome) : string]; nested exception is org.hibernate.TypeMismatchException: left and right hand sides of a binary logic operator were incompatible [java.util.List(org.loja.model.categoria.Categoria.nome) : string]
How I can change the method to make work for both types of attributes?
Advertisement
Answer
I manage to solve this issue with the approach below, using java reflection to detect the type of the field trying to be queried, and using a proper sql command. Don’t know how efficient this can be; if anyone have a better solution to this, feel free to add another answer with it.
public List<E> search(String key, Object value) throws NoSuchFieldException { EntityManager entityManager = getEntityManager(); entityManager.getTransaction().begin(); List result; Field field = clazz.getDeclaredField(key); ParameterizedType listType = (ParameterizedType) field.getGenericType(); Class<?> classElement = (Class<?>) listType.getActualTypeArguments()[0]; String nome = classElement.getSimpleName(); Field field2[] = classElement.getDeclaredFields(); String attr = field2[field2.length - 1].getName(); if(field != null) { if(field2 != null) { result = entityManager.createQuery("SELECT a FROM "+clazz.getSimpleName()+" a, "+nome+" b WHERE b."+attr+" LIKE '"+value+"%'").getResultList(); } else { result = entityManager.createQuery("SELECT a FROM "+clazz.getSimpleName()+" a, "+nome+" b WHERE b LIKE '"+value+"%'").getResultList(); } } else { result = entityManager.createQuery("SELECT a FROM "+clazz.getSimpleName()+" a WHERE a."+key+" LIKE '"+value+"%'").getResultList(); } entityManager.getTransaction().commit(); entityManager.close(); return result; }
UPDATE I got one issue with the code above: in the first query (of the three in the if/else), it’s always returned all the elements of the table, almost if the LIKE was being ignored.