Filter Criteria by attribute with #Convert - spring

I have a simple class with a list of Strings and this list is converted to be one column in db with #Convert and now i'm trying to create a criteria based on type attrbute.
#Entity(name = "my_table")
public class MyTable implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
#Convert(converter = StringListConverter.class)
private List<String> type;
}
and criteria :
c2.add(Restrictions.ilike("type", matchValue, MatchMode.ANYWHERE));
but I got this exception :
org.springframework.orm.jpa.JpaSystemException: Error attempting to apply AttributeConverter; nested exception is javax.persistence.PersistenceException: Error attempting to apply AttributeConverter
*all entries have a value and I use a psql db

It is not possible right now with Hibernate.
Please see the bug ticket: https://hibernate.atlassian.net/browse/HHH-9991

Related

How to update column in JPA native query which annothed with #Lob

I have an entity class and repository. Here I'm trying to execute update query but not working.
How to update Lob column in native query or any another solution on jpa query to update Lob column.
#Entity
#Table(name = "comment")
public class Comment implements Serializable {
#Basic
#Lob
#Column(name="Article_COMMENT", columnDefinition="TEXT")
private String articleComment;
#Basic
#Column(name = "ID_ARTICLE")
private Long articleId;
}
#Repository
public interface commentRepository extends JpaRepository<Comment, Long> {
#Query(value = "UPDATE comment set articleComment=: articleComment WHERE articleId =: articleId", nativeQuery=true)
void updateComment(#Param("articleComment") String articleComment, #Param("articleId") Long articleId );
}
Error:
No results were returned by query.
JpaSystemException thrown with message: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet
Your question is very vague so I can answer on assumptions only. I think You want to update the articalComment field of your Entity. You can simply use .save() method of JpaRepository. Your code should be as follows. Here I am also assuming that your articleId is unique identifier to your entity class.
#Entity
#Table(name = "comment")
public class Comment implements Serializable {
#Basic
#Lob
#Column(name="Article_COMMENT", columnDefinition="TEXT")
private String articleComment;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_ARTICLE")
private Long articleId;
}
Now your Id should be unique and has a #Id Annotation to identify it inside spring data JPA.
You don't have to add any code inside of your JPA repository. Simply call commentRepository.save(commentObject) method. If commentObject has an ID as 0 then a new Comment will be created. If the ID is a positive value and is present in your table that particular row will be updated not created.
remove the space try this way
UPDATE comment set articleComment=:articleComment WHERE articleId =:articleId

Problem Retrieving Nextval in JPA Application

I need have a need to return nextVal at various times in my application. I have an entity class like the following:
#Entity
#Table(name = "TBL_CACL")
public class Cacl {
#Id
#SequenceGenerator(name = "caclGenerator", sequenceName = "caclSeq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "calcGenerator")
#Column(name = "ID")
private Integer id;
// more stuff below....
, and I added the following in my repository interface:
#Repository
public interface CaclRepository extends JpaRepository<Cacl, Integer> {
#Query(value = "SELECT caclSeq.nextval FROM Cacl", nativeQuery = true)
Long getNextSeriesId();
However when I attempt to read it like this:
long nextval = caclRepository.getNextSeriesId() + 1;
, I get this exception:
(can't show entire stack trace)
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: relation "cacl" does not exist
Its puzzling to me that I am getting error "cacl does not exist" because this application has been up and working for some time. All that I have done is add the #SequenceGenerator, updated the #GeneratorValue to link to the #SequenceGenerator annotation, and create the new query. I would be grateful for any ideas as to what I am doing wrong. thanks
My answer is based on simplifying my approach some. Now I am simply using the default sequences supplied by postgress. So for instance now I have:
#Entity
#Table(name = "TBL_CACL")
public class Cacl {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Integer id;
#Column(name="NAME")
private String name;
// more stuff below...
, then in the repository (after querying postgress to get default sequences) I have:
#Query(value = "select last_value from tbl_cacl_id_seq", nativeQuery = true)
public Integer getCurrentVal();
And then:
int nextval = caclRepository.getCurrentVal();
works fine.
you could try removing the native query
#Query(value = "SELECT nextval('caclSeq')", nativeQuery =
true)
Long getNextSeriesId();

How to search nested property in Hibernate Criteria

My entity User has a nested property (in Oracle, it maps to a string field format as JSON) like the following snippet:
#Entity(name = "users")
public class User extends Auditable implements Serializable {
private Long id;
private String username;
private String password;
#Convert(converter = UserInformationConverter.class)
private UserInfomation additionalInformation;
}
public class UserInfomation {
private String email;
private String phoneNumber;
}
And then, I would like to search by the "email" property in the "additionalInformation" field in Criteria query. I tried:
predicate = cb.and(predicate, cb.like(root.get("additionalInformation").get("email"), cb.parameter(String.class, "email")));
But I got the error:
"Illegal attempt to dereference path source [null.additionalInformation] of basic type; nested exception is java.lang.IllegalStateException: Illegal attempt to dereference path source [null.additionalInformation] of basic type"
Please suggest me some solutions.
You can use the criteriaBuilder like:
cb.like(cb.lower(root.get("additionalInformation").get("email"));

How to prevent saving of referred entity when using #IdClass?

I have two entities, Type and TypeValue. Each Type can have several TypeValues. While trying to persist a new TypeValue, I get a database error that Type already exists (which is correct, but I don't want to add it again, I want to add just a new 'TypeValue'). I have similar classes without IdClass that are working, so I assume that either the #IdClass definition is wrong or I forgot to define something so that the referred object is not updated.
How to prevent saving of the referred entity Type when using #IdClass for TypeValue?
Class definitions:
#Entity
#Table(name = "TYPE", schema = "VOC")
public class Type implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "TYPEID")
private String typeID;
#Column(name = "NAME")
private String name;
#OneToMany(mappedBy = "type")
private List<TypeValue> listTypeValue;
// constructor, getter, setter, equals, hashcode, ...
}
#Entity
#IdClass(TypeValueID.class)
#Table(name = "TYPE_VALUE", schema = "VOC")
public class TypeValue implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
#JoinColumn(name = "TYPEID")
#ForeignKey(name = "TYPEVALUE_FK")
private Type type;
#Id
#Column(name = "VALUE")
private String value;
// constructor, getter, setter, equals, hashcode, ...
}
public class TypeValueID implements Serializable {
private static final long serialVersionUID = 1L;
String type;
String value;
// equals, hashcode
}
Example of usage:
Type type = ... // get existing type with typeID "DETAIL"
Session session = sessionFactory.getCurrentSession();
TypeValue newTypeValue = new TypeValue(type, "new value");
session.save(newTypeValue);
session.flush();
Thrown exception:
SEVERE: Servlet.service() for servlet [spring] in context with path [/project] threw exception [Request processing failed; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "type_pkey"
Detail: Key (typeid)=(DETAIL) already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2455)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2155)
...
please change your String typeID to int or long. Then use #GeneratedValue for auto-increment.
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private int typeID ;
Check this example
#Entity
#Table(name = "USERS")
#Proxy(lazy = false)
public class User {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private int uID ;
private String uName ;
private String uEmail ;
private String uPassword;
#OneToMany(cascade=CascadeType.ALL,fetch = FetchType.EAGER)
private List<Reminder> uReminders = new ArrayList<>();
Next Entity
#Entity
#Proxy(lazy = false)
public class Reminder {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private int reminderID ;
private Date reminderDate ;
private String reminderDescription ;
You have defined the foreign key column with #Id.
#Id
#ManyToOne
#JoinColumn(name = "TYPEID")
#ForeignKey(name = "TYPEVALUE_FK")
private Type type;
So it is expecting unique value in the column "type".Hope this may help.
The type attribute in the TypeValueID class is wrong, the class should look like this:
public class TypeValueID implements Serializable {
private static final long serialVersionUID = 1L;
Type type;
String value;
// equals, hashcode
}
The JPA Persistence API 2.1 documentation states:
The names of the fields or properties in the primary key class and the
primary key fields or properties of the entity must correspond and
their types must match according to the rules specified in Section
2.4, “Primary Keys and Entity Identity” and Section 2.4.1, “Primary Keys Corresponding to Derived Identities”.
And the rule that applies in this case is:
If the composite primary key class is represented as an id class, the
names of primary key fields or properties in the primary key class and
those of the entity class to which the id class is mapped must
correspond and their types must be the same.

EntityNotFoundException in Hibernate Many To One mapping however data exist

I'm getting an error
Caused by: javax.persistence.EntityNotFoundException: Unable to find tn.entities.AgenceBnq with id 01
when I get AgenceBnq through Employee
Employee class:
#Table(name = "EMPLOYEE")
#NamedQuery(name = "Employee.findById", query = "SELECT e FROM Employee e WHERE e.employeMat = ?1"),
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "EMPLOYEE_MAT", unique = true, nullable = false, length = 15)
private String employeeMat;
...
#ManyToOne
#JoinColumn(name = "AGENCE_COD")
private AgenceBnq agenceBnq;
}
#Entity
#Table(name="AGENCEBNQ")
public class AgenceBnq implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="AGENCE_COD", unique=true, nullable=false, length=10)
private String agenceCod;
...
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="agenceBnq")
private Set<Employee> employees;
}
I'm calling namedQuery Employee.findById in DAO to retrieve data and I have to get AgenceBnq from Employee but get this error while calling query.getResultList()
#NotFound( action = NotFoundAction.IGNORE) isn't useful for me because data exist in AGENCEBNQ table and I have to retrieve date through Employee.
Is this a bug in hibernate ? I'm using hibernate version 3.6.7.Final
Firstly, You dont need query for it, the EnityManger.find(Employee.class, YOUR_ID) will do the job.
Secondly dont use ? in your queries but names (e.employeMat = :id) as it is easier to debug and less error prones for complicated queries.
Finally, check your DB table if the AGENCE_COD column in Employee table really contains the valid ID for your entitity that crashes (and that it length matches the ID length of AgenceBnq). It should work, the typical reason why it doesnt will be that your Employe.AGENCE_COD has defualt value and when creatubg the new EMploye you add it only to the Agence but you did not set Agence in the Employ.

Resources