Hibernate cannot resolve type with enum - java

I have two entities and one with a field of a specific enum. Now I want to retrieve all that have a specific enum value.
#Entity
#Table(name = "AlarmEvent")
#XmlRootElement
public class AlarmEvent implements Identifiable {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "guid")
#Column(name = "Id", columnDefinition = "uniqueidentifier")
private String id;
#ManyToOne
#JoinColumn(name = "AlarmType_Id")
#XmlJavaTypeAdapter(EntityAdapter.class)
private AlarmEventDefinition alarmType;
#Column(name = "Timestamp", nullable = false)
private Date timestamp;
#Override
#XmlTransient
public String getIdentifier() {
return id;
}
public AlarmEventDefinition getAlarmType() {
return alarmType;
}
public void setAlarmType(AlarmEventDefinition alarmType) {
this.alarmType = alarmType;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
}
and the second entity
#Entity
#Table(name = "AlarmEventDefinition")
#XmlRootElement
public class AlarmEventDefinition implements Identifiable {
public static enum AlarmEventDefinitionType {
Start, End, Trigger, Report
}
#Id
#Column(name = "Id")
private Integer id;
#Column(name = "Name_DE", length = 256)
private String nameDe;
#Column(name = "Type")
#Enumerated(EnumType.STRING)
private AlarmEventDefinitionType type;
#OneToMany(mappedBy = "alarmType", fetch = FetchType.LAZY)
#XmlTransient
private List<AlarmEvent> events;
public List<AlarmEvent> getEvents() {
return events;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNameDe() {
return nameDe;
}
public void setNameDe(String nameDe) {
this.nameDe = nameDe;
}
public AlarmEventDefinitionType getType() {
return type;
}
public void setType(AlarmEventDefinitionType type) {
this.type = type;
}
}
Now I want to do this
List<AlarmEvent> result = (List<AlarmEvent>) session.createCriteria(AlarmEvent.class)
.add(Restrictions.eq("alarmType.type", AlarmEventDefinitionType.Trigger))
.list();
To retrieve all AlarmEvents thiers AlarmEventDefinitions type is Trigger.
Hibernate says:
org.hibernate.QueryException: could not resolve property:
alarmType.type of: datamodel.AlarmEvent

You just have an alarmType property defined in the AlarmEvent class, there is no alarmType.type. That's the error message is saying.
You need to extend the criteria to the associated class AlarmEventDefinition. The code should be something like this:
List<AlarmEvent> result = (List<AlarmEvent>) session.createCriteria(AlarmEvent.class)
.createCriteria("alarmType").add(Restrictions.eq("type", AlarmEventDefinitionType.Trigger))
.list();

Related

Criteria query returning infinite nested result

I have 3 entities Movie, Show and Theatre with below relationship
Relations
#Entity
#Table(name = "theatre")
public class Theatre {
#Id
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "town")
private String town;
#OneToMany(mappedBy = "theatre", orphanRemoval = true)
private List<Show> shows = new ArrayList<>();
public List<Show> getShows() {
return shows;
}
public void setShows(List<Show> shows) {
this.shows = shows;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
#Table(name = "show")
public class Show {
#Id
#Column(name = "id", nullable = false)
private Long id;
#ManyToOne
#JoinColumn(name = "theatre_id")
private Theatre theatre;
#ManyToOne
#JoinColumn(name = "movie_id")
private Movie movie;
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
public Theatre getTheatre() {
return theatre;
}
public void setTheatre(Theatre theatre) {
this.theatre = theatre;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
#Table(name = "movie")
public class Movie {
#Id
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy = "movie", orphanRemoval = true)
private List<Show> shows = new ArrayList<>();
public List<Show> getShows() {
return shows;
}
public void setShows(List<Show> shows) {
this.shows = shows;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Now when I try to fetch list of Theatres for a movie name I'm getting infinite nested result. As a result I'm getting StackOverflow error as well.
Is criteria query not suitable here? Or the relationship is wrong? Or criteria query is wrong itself.
Criteria query
public List<Theatre> findTheatresByMovieAndDate(String movieName) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Theatre> query = builder.createQuery(Theatre.class);
Root<Theatre> fromTheatres = query.from(Theatre.class);
Join<Theatre, Show> shows = fromTheatres.join("shows");
Join<Show, Movie> movie = shows.join("movie");
List<Predicate> conditions = new ArrayList<>();
conditions.add(builder.equal(movie.get("name"), movieName));
TypedQuery<Theatre> typedQuery = entityManager.createQuery(query
.select(fromTheatres)
.where(conditions.toArray(new Predicate[] {}))
.orderBy(builder.asc(fromTheatres.get("id")))
.distinct(true)
);
return typedQuery.getResultList();
}
Thanks in advance

ModelMapper fail to convert java.util.list to java.util.list on DeleteMapping

good day everyone,
i have this project where i use the ModelMapper to mat my entities to DTOs and vise-versa, and also have a class with #ElementCollection relation.
the mapper seems to work fine for all other methods and it just output the entity as i want, however when it comes to delete mapping i get the following error printed along with a 500 http status. here's the error:
"ModelMapper mapping errors:\r\n\r\n1) Converter org.modelmapper.internal.converter.CollectionConverter#ddb7bc7 failed to convert java.util.List to java.util.List.\r\n\r\n1 error"
here is code:
the entity class:
#Entity
#Table(name = "quiz_engines")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(
value = {"lastModified"},
allowGetters = true
)
public class Engine implements Model {
#Id
#Column(name = "engine_id", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY,optional = false, targetEntity = com.QCMGenerator.QCMGenerator.Model.Test.class)
#JoinColumn(name = "test_id", referencedColumnName = "test_id", nullable = false, updatable = false)
#OnDelete(action = OnDeleteAction.NO_ACTION)
#JsonIgnore
private Test test;
#Column(name = "quiz_name", nullable = false)
#NotNull
private String name;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "last_modified", nullable = false)
#LastModifiedDate
private Date lastModified;
#ElementCollection
#CollectionTable(name = "engine_constraints", joinColumns = #JoinColumn(name = "engine_id"))
private List<EngineConstraint> constraints;
public Engine() {
}
public Engine(#NotNull String name, List<EngineConstraint> constraints) {
this.name = name;
this.constraints = constraints;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Test getTest() {
return test;
}
public void setTest(Test test) {
this.test = test;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public List<EngineConstraint> getConstraints() {
return constraints;
}
public void setConstraints(List<EngineConstraint> constraints) {
this.constraints = constraints;
}
}
the DTO class:
public class EngineDTO implements ModelDTO {
private Long id;
#JsonIgnore
private TestDTO test;
private String name;
private Date lastModified;
private List<EngineConstraint> constraints;
public EngineDTO() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public TestDTO getTest() {
return test;
}
public void setTest(TestDTO test) {
this.test = test;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public List<EngineConstraint> getConstraints() {
return constraints;
}
public void setConstraints(List<EngineConstraint> constraints) {
this.constraints = constraints;
}
}
the Delete Controller:
#DeleteMapping("/{engineID}")
public ResponseEntity<NonPaginatedResponse> deleteEngine(
#PathVariable(value = "testID") Long testID,
#PathVariable(value = "engineID") Long engineID
){
if(!testRepo.existsById(testID)){
throw new ResourceNotFoundException("No test with the ID '"+testID+"' was found...");
}
return engineRepo.findById(engineID).map(engineFound -> {
engineRepo.delete(engineFound);
return ResponseEntity.status(HttpStatus.OK).body(
ResponseBodyBuilder.getSingleResponse(
convertToDTO(engineFound),
new ModelDTO[]{ convertToDTO(testRepo.findById(testID).get()) },
"delete"
)
);
}
).orElseThrow(
() -> new ResourceNotFoundException("No Engine with the ID '"+engineID+"' was found...")
);
}
hope you guys can help with this one, thank for your time everyone and have a good day.

Foreign key constraint is not created in one-to-one relationship in jpa

I have one-to-one relationship with the following configuration:
#Entity
#Table(name = "org")
#SequenceGenerator(name = "default_gen", sequenceName = "haj_rasoul", allocationSize = 1)
public class Organization extends BaseEntity<Long> {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and this class:
#Entity
#Table(name = "product")
#GenericGenerator(name = "default_gen", strategy = "foreign", parameters = #Parameter(name = "property", value = "reza"))
public class Product extends BaseEntity<Long> {
#Column(name = "DD")
private String description;
#Column(name = "PP")
private BigDecimal price;
#Column(name = "MM")
private String imageUrl;
#OneToOne
#PrimaryKeyJoinColumn(referencedColumnName = "id")
private Organization reza;
public Organization getReza() {
return reza;
}
public void setReza(Organization reza) {
this.reza = reza;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
and the BaseEntity:
#MappedSuperclass
public abstract class BaseEntity<T> implements Serializable {
private static final long serialVersionUID = 4295229462159851306L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "default_gen")
private T id;
#Column(name = "updatedby")
private Date updatedDate;
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
}
When the application is started with the update mode for creation the models,
they are created successfully but foreign key Organization does not exist in the Product, another hand the record of Organization can be deleted in the event that it is in the Product as foreign key.
Where is wrong?
How do i fix this problem?

JPA CriteriaBuilder Subquery multiselect

I have a question about Subquery class in jpa.
I need to create subquery with two custom field, but subquery doesn't have multiselect method and select method has Expression input parameter(In query this is Selection) and constact method not suitable.
Also I have question about join subquery results, It is possible? And how to?
I have:
Chain Enitity
public class Chain {
#Id
#Column(name = "chain_id")
#GeneratedValue(generator = "seq_cha_id", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "seq_cha_id", sequenceName = "SEQ_CHA_ID", allocationSize = 1)
private Long id;
#Column(name = "user_id")
private Long userId;
#Column(name = "operator_id")
private Long operatorId;
#Column(name = "subject")
private String subject;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "chain")
private List<Message> messages;
#Column(name = "status")
private Status status;
public Long getOperatorId() {
return operatorId;
}
public void setOperatorId(Long operatorId) {
this.operatorId = operatorId;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSubject() {
return subject;
}
public void setSubject(String theme) {
this.subject = theme;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
}
Message Enitity
public class Message {
#Id
#Column(name = "message_id")
#GeneratedValue(generator = "seq_mess_id", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "seq_mess_id", sequenceName = "SEQ_MESS_ID", allocationSize = 1)
private Long id;
#Column(name = "user_id")
private Long userId;
#Column(name = "message", nullable = true, length = 4000)
private String message;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "chain_id")
private Chain chain;
#Column(name = "creation_date")
private Date date;
#Column(name = "status")
private Status status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Chain getChain() {
return chain;
}
public void setChain(Chain chain) {
this.chain = chain;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
Wrapper for query
public class MessageWrapper {
private final Long chainId;
private final Long messageId;
public MessageWrapper(Long chainId, Long messageId) {
this.chainId = chainId;
this.messageId = messageId;
}
}
I need to create this query (this is part of query, another part I get from predicates. JPQL not suitable)
SELECT ch.*
FROM hl_chain ch,
(SELECT mes.chain_id,
max(message_id) message_id
FROM hl_message mes
GROUP BY chain_id) mes
WHERE mes.chain_id = ch.chain_id
ORDER BY message_id;
In Subquery I do
Subquery<MessageWrapper> subquery = criteriaQuery.subquery(MessageWrapper.class);
Root<Message> subRoot = subquery.from(Message.class);
subquery.select(cb.construct(
MessageWrapper.class,
subRoot.get(Message_.chain),
cb.max(subRoot.get(Message_.id))
));
But, the subquery doesn't have select with CompoundSelection in params and I can't use the CriteriaBuilder construct method.
A view on database mapped as an entity will do the job you need.
It is mapped as a normal table only with the tag #View instead.
I did the same on my projects.
You can call native queries from JPA, for example:
Query q = em.createNativeQuery("SELECT p.firstname, p.lastname FROM Person p");
List<Object[]> persons= q.getResultList();
for (Object[] p : persons) {
System.out.println("Person "
+ p[0]
+ " "
+ p[1]);
}
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<MessageWrapper> q = cb.createQuery(MessageWrapper.class);
Root<Chain> c = q.from(Chain.class);
Join<Chain, Message> m = p.join("messages");
q.groupBy(c.get("id"));
q.select(cb.construct(MessageWrapper.class, c.get("id"), cb.max(m.get("id"))));

How to join Maps

How to join newMap detals in custMap.
Map<String, Customer> custMap= new HashMap<String,Customer>();
Map<String, DoCustomer> newMap= new HashMap<String,DoCustomer>();
for (Map.Entry<String, DoCustomer> cust: newMap.entrySet()) {
custMap.put(cust.getKey(),cust.getValue());
}
public class DoCustomer {
private Long id;
private String custName;
private String description;
private String status;
private List<DoCustomerBranch> doCustomerBranch=new ArrayList<DoCustomerBranch>
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
getter/setters of doCustomerBranch
}
#Entity
#Table(name = "CUSTOMER")
public class Customer implements Serializable{
private static final long serialVersionUID = 1L;
private Long id;
private String custName;
private String description;
private String createdBy;
private Date createdOn;
private String updatedBy;
private Date updatedOn;
private Set<CustomerBranch> customerBranch=new HashSet<CustomerBranch>
#Id
#GeneratedValue(generator = "CUSTOMER_SEQ")
#SequenceGenerator(name = "CUSTOMER_SEQ", sequenceName = "CUSTOMERN_SEQ", allocationSize = 1)
#Column(name = "ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "CUST_NAME",nullable=false)
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
#Column(name = "DESCRIPTION")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "CREATED_BY", length = 50)
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CREATED_ON")
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
#Column(name = "UPDATED_BY", length = 50)
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "UPDATED_ON")
public Date getUpdatedOn() {
return updatedOn;
}
public void setUpdatedOn(Date updatedOn) {
this.updatedOn = updatedOn;
}
#OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY, mappedBy = "customer")
public Set<CustomerBranch> getCustomerBranch() {
return customerBranch;
}
public void setCustomerBranch(Set<CustomerBranch> customerBranch) {
this.customerBranch = customerBranch;
}
}
CustomerBranch
#Entity
#Table(name = "CUSTOMER_BRANCH")
public class CustomerBranch implements Serializable{
#Id
#GeneratedValue(generator = "CUSTOMER_BRANCH_SEQ")
#SequenceGenerator(name = "CUSTOMER_BRANCH_SEQ", sequenceName = "CUSTOMER_BRANCH_SEQ", allocationSize = 1)
#Column(name = "ID")
private Long id;
private String branchName;
private String branchAddress;
private Customer customer;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "BRANCH_NAME",nullable=false)
public String getBranchName() {
return branchName;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "MOBEE_CUSTOMER")
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
The problem with your code is that you want to put a DoCustomer in a Customer container. It only works if DoCustomer is a subclass of Customer.
Edit 1: You could use BeanUtils to convert a DoCustomer into a Customer. Here is a good tutorial.
Do you mean:
custMap.putAll(newMap)
As everyone else has pointed out, we need to know what DoCustomer is to be able to help.
But, from what you have given us, I'd suggest casting each DoCustomer to a Customer or, more correctly, making a new Customer from the fields of each DoCustomer.
Something like:
custMap.put(cust.getKey(), new Customer(cust.getValue().getId(), cust.getValue().getCustName(), and so on..));
inside your for loop.
I can see the customer class defined you have provided doesn't have a constructor, so naturally you would have to add one to it

Categories