modifying query not working : no property found exception - spring

i am trying to modify the card entity with below mentioned code.
public interface CardRepository extends JpaRepository<Card, Integer>{
#Modifying
#Query(name="update Card c set c.status=4 where c.id=?1")
public void setCardStatus(int id);
}
Card Class is associated with status.
#Entity
#Table(name="card")
public class Card {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="card_no")
private String cardNo;
#ManyToOne
#JoinColumn(name="status_id",nullable=false,insertable=true,updatable=true)
private Status status;
... getter setters...
}
Below mentioned is the exception generated.
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property set found for type Card!
Changing method name to modify also does not work also.
any help is appreciated please...

Don't use the name setCardStatus! Change the name to something like changeCardStatus

Related

Cannot invoke "org.hibernate.mapping.PersistentClass.getTable()" because "classMapping" is null

I have an entity "MasterSegment" with a composite key as the primary key. This key has a reference to another entity "BkrApplication". When I start the app without Liquibase, tables are generated perfectly and everything works fine.
public class MasterSegment extends Auditable {
#EmbeddedId
private MasterSegmentId id;
#OneToOne
#MapsId("appId")
private BkrApplication app;
// getters setters omitted
}
#Embeddable
public class MasterSegmentId implements Serializable {
#Column
private String name;
#Column(name = "app_id", nullable = false)
private Long appId;
// getters setters omitted
}
The problem is when I try to generate a Liquibase migration using mvn clean install liquibase:diff, I get the following error: Cannot invoke "org.hibernate.mapping.PersistentClass.getTable()" because "classMapping" is null.
Without any hint in the exception message, and after many hours of debugging, I noticed that #MapsId causes the issue. I try to remove it and I got mapping issues.
Any help would be much appreciated.
Thanks

Spring Data Rest Does Not Update Default Value in DB

I have a Spring Boot application using Spring Data REST. I have a domain entity called User with a boolean field isTeacher. This field has been already setup by our DBA in the User table with type bit and a default value of 1:
#Data
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // This Id has been setup as auto generated in DB
#Column(name = "IS_TEACHER")
private boolean isTeacher;
}
And the User repository:
public interface UserRepository extends CrudRepository<User, Long>{
}
I was able to add a new user by giving the below request and POST to http://localhost:8080/users, a new user was created in the DB having isTeacher value 1:
{
"isTeacher" : true
}
However, when I tried to change IS_TEACHER by giving PATCH (or PUT) and this request:
{
"isTeacher" : false
}
The response showed that "isTeacher" is still true and the value didn't get changed in the table either. Can someone please let me know why this is happening?
The issue is due to #Data annotation of lombok is ignoring if you have a field that start with isXx it generates getters and setters to boolean with isTeacher for getters and setTeacher for setters then you are not able to update correctly your property, if you put "teacher" when updating should work but you should solve this by overriding that setter.
#Setter(AccessLevel.NONE) private boolean isTeacher;
public void setIsTeacher(boolean isTeacher) {
this.isTeacher = isTeacher;
}

How do I get Spring's Data Rest Repository to retrieve data by its name instead of its id

I am using Spring Data's Rest Repositories from spring-boot-starter-data-rest, with Couchbase being used as the underlining DBMS.
My Pojo for the object is setup as so.
#Document
public class Item{
#Id #GeneratedValue(strategy = UNIQUE)
private String id;
#NotNull
private String name;
//other items and getters and setters here
}
And say the Item has an id of "xxx-xxx-xxx-xxx" and name of "testItem".
Problem is, that when I want to access the item, I need to be accessible by /items/testItem, but instead it is accessible by /items/xxx-xxx-xxx-xxx.
How do I get use its name instead of its generated id, to get the data.
I found out the answer to my own question.
I just need to override the config for the EntityLookup.
#Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.withEntityLookup().forRepository(UserRepository.class).
withIdMapping(User::getUsername).
withLookup(UserRepository::findByUsername);
}
}
Found the info here, though the method name changed slightly.
https://github.com/spring-projects/spring-data-examples/tree/master/rest/uri-customization
If you want query the item by name and want it perform as querying by id,you should make sure the name is unique too.You cant identify a explicit object by name if all objects have a same name,right?
With jpa you could do it like:
#NotNull
#Column(name="name",nullable=false,unique=true)
private String name;

Spring Data JPA and Generics

I have an entity that looks like this
#Entity(name = "encounter_pdf_export")
public class EncounterPDFExport<T extends Encounter> implements Serializable {
public static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long pdfExportId;
#Any(metaColumn = #Column(name = "encounter_type"))
#Cascade(CascadeType.ALL)
#AnyMetaDef(
idType = "long",
metaType = "string",
metaValues = {
#MetaValue(value = "FooEncounter", targetEntity = FooEncounter.class)
})
#JoinColumn(name = "encounter_id")
private T encounter;
The abstract type that I'm extending is:
public abstract class Encounter {
public abstract Long getEncounterId();
}
Here is my Spring Data Repository
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter_encounterId(#Param("encounterId") Long encounterId);
}
I am getting a stack trace when starting up the application related to to the findOneByEncounter_encounterId method:
Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [encounter] on this ManagedType [com.iimassociates.distiller.domain.EncounterPDFExport]
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.checkNotNull(AbstractManagedType.java:144)
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.getAttribute(AbstractManagedType.java:130)
at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:468)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.getTypedPath(JpaQueryCreator.java:300)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:243)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:148)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:88)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:46)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:116)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$CountQueryPreparer.<init>(PartTreeJpaQuery.java:237)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:65)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:100)
I am assuming that either Spring Data JPA doesn't support abstracted/generic fields? If that's the case, would creating a #Query be a sufficient workaround?
Not sure if this will be helpful to anyone, but I did get this working.
Removed the abstract class and made it an interface with a single public getEncounterId() method
Modified FooEncounter to implement the above interface
Removed generics from the EncounterPDFExport class
Modified the encounter field to utilize the above interface rather than a generic
Apparently, I'm hitting some Hibernate bug/limitation when accessing fields within FooEncounter. Accessing Encounter within EncounterPDFExport works OK, though. I modified my Spring Data JPA Repository to look like the following (note the modification from finding by encounter.encounterId vs. just encounter):
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter(#Param("encounter") Encounter encounter);
}
The Hibernate bug in question seems to be related to https://jira.spring.io/browse/DATAJPA-836.

Spring Data query over two documents

I have an m:n connection in my MongoDB, MessageUserConnection is the class between User and Message.
Now I will get all MessageUserConnections where MessageUserConnection#confirmationNeeded is true, read is false and Message#receiveDate is not older than the last week.
Is there any possibility to do this with Spring Data?
Thanks a lot!
public class MessageUserConnection {
#Id
private String id;
#DBRef
private User userCreatedMessage;
#DBRef
private Message message;
private Boolean confirmationNeeded;
private Boolean read;
}
public class Message {
#Id
private String id;
private String title;
private String message;
private DateTime receiveDate;
}
[EDIT]
I have tried it by my own:
#Query("FROM MessageUserConnection AS muc WHERE muc.confirmationNeeded = ?0 AND muc.message.receiveDate = ?1")
List<MessageUserConnection> findMessageUserConnectionByConfirmationNeededAndReceiveDate(final Boolean confirmationNeeded, final DateTime receiveDate);
and I get the following exception:
Caused by: com.mongodb.util.JSONParseException:
FROM MessageUserConnection AS muc WHERE muc.confirmationNeeded = "_param_0" AND muc.message.receiveDate = "_param_1"
Does anyone know what I am doing wrong here?
Thanks a lot!
[EDIT]
I run into another problem. My query currently looks like this.
#Query("{$and : [{'confirmationNeeded' : ?0}, {'message.receiveDate' : ?1}]}")
where confirmationNeeded is a boolean and message.receiveDate is Joda#DateTime. With this query I get the following exception:
org.springframework.data.mapping.model.MappingException: Invalid path reference message.receiveDate! Associations can only be pointed to directly or via their id property!
Does that mean that I only can join to message.id?
Thanks a lot!

Resources