I have a custom JPQL query in a Spring CrudRepository that's not working.
This is my entity class, PK class and CrudRepository interface for the entity:
#Entity(name = "TBL_PRINCIPAL_CREDENTIAL")
public class PrincipalCredential {
#EmbeddedId
private PrincipalCredentialPK principalCredentialPK;
// ...getter & setter for principalCredentialPK
}
#Embeddable
public class PrincipalCredentialPK implements Serializable {
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
#Column(name = "CREDENTIAL_ID", nullable = false)
private Integer credentialID;
#Column(name = "CREDENTIAL_TYPE_ID", nullable = false)
private String credentialTypeID;
// ...getters & setters for all fields...
}
#Transactional
public interface PrincipalCredentialRepository extends CrudRepository<PrincipalCredential, PrincipalCredentialPK> {
#Modifying
#Query("update PrincipalCredential pc set pc.principalCredentialPK.principalID =:newPrincipalID " +
"where pc.principalCredentialPK.principalID =:oldPrincipalID and pc.principalCredentialPK.principalTypeID =:principalType")
void updatePrincipalID(#Param("oldPrincipalID") String oldPrincipalID, #Param("newPrincipalID") String newPrincipalID,
#Param("principalType") String principalType);
}
When I start my project using SpringBoot the repository bean cannot be instantiated and I get the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'principalCredentialRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract void com.consorsbank.services.banking.caas.repositories.PrincipalCredentialRepository.updatePrincipalID(java.lang.String,java.lang.String,java.lang.String)!
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract void com.consorsbank.services.banking.caas.repositories.PrincipalCredentialRepository.updatePrincipalID(java.lang.String,java.lang.String,java.lang.String)!
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: PrincipalCredential is not mapped [update PrincipalCredential pc set pc.principalCredentialPK.principalID =:newPrincipalID where pc.principalCredentialPK.principalID =:oldPrincipalID and pc.principalCredentialPK.principalTypeID =:principalType]
Also for another repository this query is working, the difference is that the PK of the other entity is simpler and both ids are provided there...
#Entity
#Table(name = "TBL_PRINCIPALS")
public class Principal implements Serializable {
#EmbeddedId
private PrincipalPK principalPK;
#OneToOne
#JoinColumn(name = "PRINCIPAL_TYPE_ID", insertable = false, updatable = false)
private PrincipalType principalType;
#Column(name = "USER_ID")
private Integer userID;
#Column(name = "VALID_UNTIL")
private Date validUntil;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "ZAAS_TBL_PRINCIPAL_CREDENTIAL",
joinColumns = {#JoinColumn(name = "PRINCIPAL_ID"), #JoinColumn(name = "PRINCIPAL_TYPE_ID")},
inverseJoinColumns = {#JoinColumn(name = "CREDENTIAL_ID"), #JoinColumn(name="CREDENTIAL_TYPE_ID")})
public Set<Credential> credentials;
// ...getters and setters...
}
#Embeddable
public class PrincipalPK implements Serializable {
#Column(name = "PRINCIPAL_TYPE_ID", nullable = false)
private String principalTypeID;
#Column(name = "PRINCIPAL_ID", nullable = false)
private String principalID;
// ...getters and setters
}
#Transactional
public interface PrincipalsRepository extends CrudRepository<Principal, PrincipalPK> {
#Modifying
#Query("update Principal p set p.principalPK.principalID =:newPrincipalID " +
"where p.principalPK.principalID =:oldPrincipalID and p.principalPK.principalTypeID =:principalType")
void updatePrincipalID(#Param("oldPrincipalID") String oldPrincipalID, #Param("newPrincipalID") String newPrincipalID,
#Param("principalType") String principalType);
}
So the above query is working...
Could someone please point out what I'm missing for the query defined in the PrincipalCredentialRepository?
The entity definition seems to be wrong. Use the following annotations
#Entity
#Table(name = "TBL_PRINCIPAL_CREDENTIAL")
public class PrincipalCredential {
//...
Related
#Entity
#Table(name = "customer", schema = "customer")
public class Customer {
#Id
#GeneratedValue
#Column(columnDefinition = "uuid", updatable = false, name = "customer_id")
private UUID customerId;
private String name;
#ManyToMany(mappedBy = "bookMembers")
Set<Reservation> reservations
}
#Entity
#Table(name = "reservation", schema = "reservation")
#NoArgsConstructor
public class Reservation {
#Id
#GeneratedValue
#Column(columnDefinition = "uuid", updatable = false, name = "reservation_id")
private UUID reservationId;
#JoinColumn(name = "reservation_id")
#Column(name = "reserved_by_customer_id")
private UUID reservedByCustomerId;
#JoinColumn(name = "menu_id")
private UUID menuId;
#ManyToMany
#JoinTable(
name = "reservation_customer",
schema = "customer",
joinColumns = {#JoinColumn(name = "reservation_id")},
inverseJoinColumns = {#JoinColumn(name = "customer_id")}
)
private Set<Customer> reservationMembers = new HashSet<>();
}
Dao Entity
#Data
#AllArgsConstructor
public class MenuCount {
private UUID menuId;
private Long count;
}
Repository
public interface ReservationRepository extends JpaRepository<Reservation, UUID> {
#Query("select new com.de.dao.MenuCount(r.menuId, count(c.customerId)) from customer c join c.reservations r group by r.menuId")
List<MenuCount> getCustomerCountGroupByMenuId();
}
I am trying to get the total number of customers for each menu Id. But when running the code getting the below error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Repository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.de.repository.Repository.getCustomerCountGroupByMenuId()!
Native -
select r.menuId, count(c.customerId) from Customer c join reservation_customer cr on c.customerId = cr.customerId join Reservation r on r.reservationId = cr.reservationId groupBy r.menuId;
Can I acheive the native query functionality using #Query() in JPA without creating an additional entity module
I have 2 classes with One-to-Many relationship
#javax.persistence.Entity
#TypeDef(name = "InquiryIdType", typeClass = InquiryIdType.class)
public class Inquiry implements Entity
{
#javax.persistence.Id
#Type(type = "InquiryIdType")
#Column(name = "id", columnDefinition = DB_ENTITY_ID_TYPE)
private InquiryId id;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "conference_session_id", nullable = false)
private ConferenceSession conferenceSession;
#Column(name = "state", nullable = false)
#Enumerated(EnumType.STRING)
private QuizStateType quizStateType;
and
public enum QuizStateType
{
IN_PROGRESS(0),
FINISHED(1),
NOT_STARTED(2),
DELETED(3);
public int value;
QuizStateType(int value)
{
this.value = value;
}
}
I need to find "Inquiry" by the Conference session Id_id and QuizStateType (is Deleted). I try, but swears at the context.
nested exception is
org.springframework.data.mapping.PropertyReferenceException: No
property is found for type QuizStateType! Traversed path:
Inquiry.quizStateType.
public interface InquiryRepository extends JpaRepository<Inquiry, UUID>
{
List<Inquiry> findByConferenceSession_idAndQuizStateTypeIs_DELETED (UUID conferenceSessionId);
}
I'm working with Java 1.7, JBOSS EAP 6.4, hibernate jpa 2.0 and database oracle.
I'm trying to modify the composite id of an entity into a simple id.
Original Classes
#Entity
#Table(name = "FOO_BAR")
#IdClass(FooBarId.class)
public class FooBar{
#ManyToOne
#JoinColumn(
name = "COD_FOO",
updatable = false,
insertable = false)
#JsonIgnore
private Foo foo;
#ManyToOne
#JoinColumn(
name = "COD_BAR",
updatable = false,
insertable = false)
#JsonIgnore
private Bar bar;
#Id
#Column(name = "COD_FOO")
private String codFoo;
#Id
#Column(name = "COD_BAR")
private String codBar;
//getter and setter
}
public class FooBarId implements Serializable {
private String codFoo;
private String codBar;
public String getCodFoo() {
return codFoo;
}
public void setCodFoo(String codFoo) {
this.codFoo = codFoo;
}
public String getCodBar() {
return codBar;
}
public void setCodBar(String codBar) {
this.codBar = codBar;
}
}
New Classes
#Entity
#Table(name = "FOO_BAR")
public class FooBar{
#Id
private Long Id;
#ManyToOne
#JoinColumn(
name = "COD_FOO",
updatable = false,
insertable = false)
#JsonIgnore
private Foo foo;
#ManyToOne
#JoinColumn(
name = "COD_BAR",
updatable = false,
insertable = false)
#JsonIgnore
private Bar bar;
#Column(name = "COD_FOO")
private String codFoo;
#Column(name = "COD_BAR")
private String codBar;
//getter and setter
}
#Entity
#Table(name = "FOO_BAR_OTHER")
public class FooBarOther{
#Id
#Column(name = "ID")
private Long id;
#Column(name = "DATA")
private String data;
#ManyToOne
#JoinColumn(
name = "ID_FOO_BAR",
referencedColumnName = "ID",
insertable = false,
updatable = false)
private FooBar fooBar;
}
No problems in the build phase.
In the deploy phase i have the following error:
[PersistenceUnit: PersistenceUnit] Unable to build EntityManagerFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: PersistenceUnit] Unable to build EntityManagerFactory
Caused by: org.hibernate.MappingException: Foreign key (FK_ljn0q2iefn1qh0dutifext8fj:FOO_BAR_OTHER [ID_FOO_BAR])) must have same number of columns as the referenced primary key (FOO_BAR [COD_FOO,COD_BAR])"}}
something saved the composite key and I can't delete it.
I tried to create a new class FooBar2 with same table FOO_BAR, same error.
I tried to create a class FooBar2 with only Id and same table, same error.
I tried to drop all database constraint, same error.
The only thing that worked was creating a new copy table of the original FOO_BAR2.
How can I fix the problem using the original table?
I have EcranChamp entity
#Entity
#IdClass(EcranChampId.class)
public class EcranChamp {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ecran")
Ecran ecran;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "champ")
Champ champ;
...
And EcranChampId
#Embeddable
public class EcranChampId implements Serializable {
private Champ champ;
private Ecran ecran;
...
Every time i am trying to save an EcranChamp element i have this following error
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to convert request element: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found
2018-09-25 12:15:42.889 WARN 14216 --- [nio-8092-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.Long' to required type 'com.kepler.portailclient.domain.model.Ecran' for property 'ecran': no matching editors or conversion strategy found
Try something like this:
#Entity
#Table(name = "<entity name>")
public class EcranChamp {
#EmbeddedId
#AttributeOverrides({ #AttributeOverride(name = "id_ecran", column = #Column(name =
"<column name>", nullable = false)),
#AttributeOverride(name = "id_champ", column = #Column(name = "<column name>", nullable = false)) })
EcranChampId id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_ecran")
Ecran ecran;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_champ")
Champ champ;
//getters & setters
}
#Embeddable
public class EcranChampId implements Serializable {
#Column(name = "id_champ", nullable = false)
private Long id_champ;
#Column(name = "id_ecran", nullable = false)
private Long id_ecran;
//getters & setters
}
You shoud use #EmbeddedId annotation.
Please, change your EcranChampId class to this:
#Embeddable
public class EcranChampId implements Serializable {
#ManyToOne
private Champ champ;
#ManyToOne
private Ecran ecran;
//getters and setters
}
And change your EcranChamp class to this:
#Entity
#Table(name = "champ_has_ecran_table_name")
#AssociationOverrides({
#AssociationOverride(name = "pk.champ", joinColumns = #JoinColumn(name = "champ_id"))
#AssociationOverride(name = "pk.ecran", joinColumns = #JoinColumn(name = "ecran_id"))
})
public class EcranChamp {
#EmbeddedId
private EcranChampId pk;
public EcranChamp() {
pk = new EcranChampId();
}
public EcranChampId getPk() {
return pk;
}
public void setPk(EcranChampId pk) {
this.pk = pk;
}
#Transient
public Champ getChamp() {
return pk.getChamp();
}
public void setChamp(Champ champ) {
pk.setChamp(champ);
}
#Transient
public Ecran getEcran() {
return pk.getEcran();
}
public void setChamp(Ecran ecran) {
pk.setEcran(ecran);
}
}
And use it like this:
public class Champ {
#OneToMany(mappedBy = "pk.champ")
private Collection<EcranChamp> ecranChamps;
//getters and setters
}
Also, if EcranChamp or EcranChampId has no other fields i will recommend you to use #ManyToMany annotation instead EcranChamp class like this:
public class Champ {
#ManyToMany
#JoinTable(
name = "champ_has_ecran_table_name",
joinColumns = #JoinColumn(name = "champ_id", referencedColumnName = "id", nullable = false),
inverseJoinColumns = #JoinColumn(name = "ecran_id", referencedColumnName = "id", nullable = false)
)
private Collection<Ecran> ecrans;
//getters and setters
}
I work with a Spring boot project and when I run, I get the following error,
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userSecurityService': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract Ecommerce.entities.User Ecommerce.repository.UserRepository.findByUsername(java.lang.String)!
I assume the last lines are what is important in the error stack,
Could not create query metamodel for method public abstract Ecommerce.entities.User Ecommerce.repository.UserRepository.findByUsername(java.lang.String)!
I have the User repository provided below,
public interface UserRepository extends CrudRepository<User, Long> {
User findByUsername(String username);
User findByEmail(String email);
}
The user entity is also provided,
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userId", nullable = false, updatable = false)
private Long userId;
private String userName;
private String password;
private String firstName;
private String lastName;
#Column(name = "email", nullable = false, updatable = false)
private String email;
private String phone;
private boolean enabled = true;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
private ShoppingCart shoppingCart;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<UserShipping> userShippingList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<UserPayment> userPaymentList;
#OneToMany(mappedBy = "user")
private List<Order> orderList;
#JsonIgnore
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<UserRole> userRoles = new HashSet<>();
// ..............
// more lines of code for overriding the methods
}
What is the issue here and how to solve it?
In Spring JPA Repository, the auto-generated finders obey the naming convention as follows.
findBy<DataMember><Op>
<Op> can be Like,Between etc..
Apparently, the name of the method findByUsername should match with the property in the user entity. In the user entity class, I have used,
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "userId", nullable = false, updatable = false)
private Long userId;
private String userName;
}
After I changed to the username from the userName, the problem is solved. I have done this after consulting other SOF posts, but, I still seek for the better explanation.