How to access element zero in HQL? - hql

I have the Entity and NamedQuery:
#Entity
#Table(name="MY_TABLE")
#NamedQueries({
#NamedQuery(name="myQuery", query="select m from MyEntity m where m.child.x = 7"
})
public class MyClass {
#Column(name="CHILD_COL")
private Child child;
// getter and setter
}
public class Child {
int x;
// getter and setter
}
Now, I want to change it to have a list o Child:
#Entity
#Table(name="MY_TABLE")
#NamedQueries({
#NamedQuery(name="myQuery", query="select m from MyEntity m where m.childs[0].x = 7"
})
public class MyClass {
#Column(name="CHILD_COL")
private List<Child> childs;
// getter and setter
}
But but the 'childs[0].x' syntax does not exist. Any idea how can I do it?

Indexed lists are supporterd by Hibernate but is important the definition.
In old way (XML mapping) you can work as follow:
In pojo:
private List<Child> childs;
In XML mapping:
<list name="childs" table="yourtable" cascade="all,delete-orphan"
inverse="false" lazy="false">
<key column="fk_to_parent"/>
<list-index column="an_integer_column"/>
<one-to-many class="Child" />
</list>
In JPA annotation you must use IndexColumn annotation as follow:
#IndexColumn(name="an_integer_column", base=0, nullable=false)
So you'll have:
#Column(name="CHILD_COL")
#IndexColumn(name="an_integer_column", base=0, nullable=false)
private List<Child> childs;
Tell me if it's OK

Related

How to exclude/disable #Entity Annotation for particular class

I want to disable #Entity Annotation for particular class.
Here is my sample code.
#Component
public class GenericDropDown{
private Integer id;
private String key;
private String value;
// Standard getter and setter
The above class is used for fetching data from multiple table for rendering different dropdown list from different tables.
How I can achieve this without #Entity Annotation
Here is my sample code.
#Component
public class GenericDropDown{
private Integer id;
private String key;
private String value;
// Standard getter and setter
#Repository
public class DropDownDao {
#Autowired
private EntityManager entityManager;
public Object runNativeQuery() {
#SuppressWarnings("unchecked")
List<Priority> o= entityManager.createNativeQuery("select Id,PRKEY,PRVALUE from Priority",Priority.class)
.getResultList();
return o;
}
}
**Error:**Unknown entity: com.min.test.Project.entity.Priority; nested exception is org.hibernate.MappingException: Unknown entity: com.min.test.Project.entity.Priority
You can select List of Objects array and map them yourself.
List<Object[]> o = entityManager.createNativeQuery("select Id,PRKEY,PRVALUE from Priority").getResltList();
List<MyClass> result = o.stream().map(arr -> new MyClass((Long) arr[0], (String) arr[1])).collect(Collectors.toList());
Or you also can use a JdbcTemplate instead of EntityManager:
#Autowired
private JdbcTemplate jdbcTemplate;
public List<MyClass> runQuery() {
String select = "select Id,yourParameterHere from Priority";
return jdbcTemplate.query(select, (rs, rowNum) -> new MyClass(rs.getLong("Id"), rs.getString("yourParameterHere")));
}

Can't access a property of a Embedded class via JPA

#Entity
#EntityListeners(AuditingEntityListener.class)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "TIPO_CONTRATO", discriminatorType = DiscriminatorType.STRING)
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Contrato extends AuditorEntity implements Serializable, Clonable {
#Column(name = "CIF_NIF")
#JsonView(Views.Buscador.class)
#JsonProperty("cifNif")
private String cifNif;
#Column(name = "NOMBRE_SOCIEDAD_PERSONA")
#JsonView(Views.Buscador.class)
private String nombreSociedadPersona;
}
And i have this Embeddable class called CuentaBancaria from Contrato table:
#Embeddable
public class CuentaBancaria implements Serializable {
private static final long serialVersionUID = 6835775213299596371L;
#Column(name = "TITULAR_CUENTA")
#JsonView(Views.Completo.class)
private String titularCuenta;
}
In ContratoRepository i'm trying doing a JPA Query finding the "titularCuenta" field of Cuenta Bancaria finding by the cifNif field of Contrato. But it's not working. What can i do to solve this?
#Query(value="SELECT c.CuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1 AND c.nombreSociedadPersona IS NOT NULL AND ROWNUM = 1")
public String getNombreLegalCliente(String cifNif);
The error which is throwing:
Caused by: org.hibernate.QueryException: could not resolve property:
CuentaBancaria of: com.xxxx.Contrato
You're missing CuentaBancaria field in Contrato class. That's why JQL complains.
Add the field in the class with #Embedded annotation:
public class Contrato extends AuditorEntity implements Serializable, Clonable {
#Embedded
private CuentaBancaria cuentaBancaria;
}
And fix the JQL expression to:
#Query(value="SELECT c.cuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1 AND c.nombreSociedadPersona IS NOT NULL AND ROWNUM = 1")
public String getNombreLegalCliente(String cifNif);
Yes, since your class [ CuentaBancaria ] is annotated with #Embeddable, it needs to be embedded in the parent class in this case [ Contrato ] with #Embedded.
Then, harnessing Spring Data JPA query Lookup strategies, you can access property fields of your embedded class with ease or you could still go by the #Query() approach
Query lookup Strategy from Spring documentation
Sample demo code with your problem with a minimal implementation:
Entity-Class
--------------
#Entity
public class Contrato{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long contratoId;
#Column(name = "CIF_NIF")
private String cifNif;
#Column(name = "NOMBRE_SOCIEDAD_PERSONA")
private String nombreSociedadPersona;
//we call the embeddable class in this parent class with #Embedded annotation
#Embedded
private CuentaBancaria cuentaBancaria
}
Embeddable-Class
-----------------
#Embeddable
public class CuentaBancaria{
#Column(name = "TITULAR_CUENTA")
private String titularCuenta;
}
Now in your ContratoRepository class, we could have
#Repository
public interface ContratoRepository extends CrudRepository<Contrato, Long> {
Optional<Contrato> findByCuentaBancariaTitularCuenta(String cifNif);
}
which interprets to JPQL snippet:
c.cuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1
NOTE: Notice the query method name matches the exact names in the classes and their corresponding fields, preceded by findBy

How to search through array in Spring Boot CrudRepository

Say, I have the following entity class:
Person.java
#Entity
public class Person {
#Id
private String name;
private String[] cars;
// Constructor, getters and setters
}
And the repository:
PersonRepository.java
public interface PersonRepository extends CrudRepository<Person, String> {
// this is unclear!
List<Person> getAllByCars...(String car)
}
Is there a method that returns all persons, whose car array contains one given car (the String parameter above)?
For me, it seems that all supported JPA keywords can only deal with single elements, but not with arrays.
Thanks for help!
Ideally, You should declare cars as a separate Entity like this
#Entity
public class Person {
#Id
private String name;
private List<Car> cars;
// Constructor, getters and setters
}
If not you should change Array to List at the least.
change
private String[] cars;
to
#ElementCollection
private List<String> cars;
Then You have to write a Query like this
#Query("select p from Person p WHERE :car in elements(p.cars)")
List<Person> getAllByCars...(#Param("car") String car)
I'm guessing at how you are currently storing the cars information and suggesting a possible solution:
#Entity
public class Car {
#Id
private String name;
#Column
private String person_name;
}
public interface CarRepository extends JpaRepository<Car, String> {
//Result will have all cars with the person_name identifying the Person #Entity
List<Car> findByName(String name);
}

Spring JPA saving distinct entities with composite primary key not working as expected, updates same entity

I have a logic that saves some data and I use spring boot + spring data jpa.
Now, I have to save one object, and after moment, I have to save another objeect.
those of object consists of three primary key properties.
- partCode, setCode, itemCode.
let's say first object has a toString() returning below:
SetItem(partCode=10-001, setCode=04, itemCode=01-0021, qty=1.0, sortNo=2, item=null)
and the second object has a toString returning below:
SetItem(partCode=10-001, setCode=04, itemCode=01-0031, qty=1.0, sortNo=2, item=null)
there is a difference on itemCode value, and itemCode property is belonged to primary key, so the two objects are different each other.
but in my case, when I run the program, the webapp saves first object, and updates first object with second object value, not saving objects seperately.
(above image contains different values from this post question)
Here is my entity information:
/**
* The persistent class for the set_item database table.
*
*/
#Data
#DynamicInsert
#DynamicUpdate
#Entity
#ToString(includeFieldNames=true)
#Table(name="set_item")
#IdClass(SetGroupId.class)
public class SetItem extends BasicJpaModel<SetItemId> {
private static final long serialVersionUID = 1L;
#Id
#Column(name="PART_CODE")
private String partCode;
#Id
#Column(name="SET_CODE")
private String setCode;
#Id
#Column(name="ITEM_CODE")
private String itemCode;
private Double qty;
#Column(name="SORT_NO")
private int sortNo;
#Override
public SetItemId getId() {
if(BooleanUtils.ifNull(partCode, setCode, itemCode)){
return null;
}
return SetItemId.of(partCode, setCode, itemCode);
}
#ManyToMany(fetch=FetchType.LAZY)
#JoinColumns(value = {
#JoinColumn(name="PART_CODE", referencedColumnName="PART_CODE", insertable=false, updatable=false)
, #JoinColumn(name="ITEM_CODE", referencedColumnName="ITEM_CODE", insertable=false, updatable=false)
})
private List<Item> item;
}
So the question is,
how do I save objects separately which the objects' composite primary keys are partially same amongst them.
EDIT:
The entity extends below class:
#Setter
#Getter
#MappedSuperclass
#DynamicInsert
#DynamicUpdate
public abstract class BasicJpaModel<PK extends Serializable> implements Persistable<PK>, Serializable {
#Override
#JsonIgnore
public boolean isNew() {
return null == getId();
}
}
EDIT again: embeddable class.
after soneone points out embeddable class, I noticed there are only just two properties, it should be three of it. thank you.
#Data
#NoArgsConstructor
#RequiredArgsConstructor(staticName="of")
#Embeddable
public class SetGroupId implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#NonNull
private String partCode;
#NonNull
private String setCode;
}
Check howto use #EmbeddedId & #Embeddable (update you might need to use AttributeOverrides in id field, not sure if Columns in #Embeddable works).
You could create class annotated #Embeddable and add all those three ID fields there.
#Embeddable
public class MyId {
private String partCode;
private String setCode;
private String itemCode;
}
Add needed getters & setters.
Then set in class SetItem this class to be the id like `#EmbeddedId´.
public class SetItem {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="partCode",
column=#Column(name="PART_CODE")),
#AttributeOverride(name="setCode",
column=#Column(name="SET_CODE"))
#AttributeOverride(name="itemCode",
column=#Column(name="ITEM_CODE"))
})
MyId id;
Check also Which annotation should I use: #IdClass or #EmbeddedId
Be sure to implement equals and hashCode in SetGroupId.
Can you provide that class?

Spring Data JPA remove child entities

I have a load repository.
#Transactional
public interface MyLoadRepository extends CrudRepository<ParentEntity, Serializable> {
}
Then is my ParentEntity.
#MappedSuperclass
public class ParentEntity {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
#Column(name = "id", unique = true)
private String uuid;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
}
Then I have multiple child entities.
#Entity
#Table(name = "EntityA")
public class EntityA extends ParentEntity {
}
#Entity
#Table(name = "EntityB")
public class EntityB extends ParentEntity {
}
Ques : I want to delete these entities separately by my repository.
If I write something like this.
#Autowired
private MyLoadRepository repository;
and then repository.deleteAll()
I get error that repository is not entity (It obiviously not).
Here I want to delete either entityA or entityB data completely based on some condition. How can I do that ?
We should create repository per entity and not on non entity classes.
So, for your case you need 2 repository classes
#Transactional
public interface EntityARepo extends CrudRepository< EntityA, String> {
}
#Transactional
public interface EntityBRepo extends CrudRepository< EntityB, String> {
}
now in service classes you can do
#Autowired
private EntityARepo repoA;
#Autowired
private EntityBRepo repoB;
and then you can call delete method based on your condition
repoA.deleteAll()
or
repoB.deleteAll()
You need to fetch the entity based on a condition. For example, if the EntityA has a primary key uuid, then you must find EntityA by uuid and then delete the EntityA.
EntityA entityA = entityARepo.findOne(uuid);
repository.delete(entityA);
EntityB entityB = entityBRepo.findOne(uuid);
repository.delete(entityB);

Resources