How to query a database having a composite key, which accepts queries where parts of the composite key are null in Spring JPA? - spring

I have a webapp that uses a database with a composite key. I need to create an API which will accept the parameters of the composite key wherein each paramenter can be null.
(for eg. If all the parameters of the composite key are set as null and query is done, then it should just return all rows in db)
I have used QueryByExampleExeccutor but it keeps throwing a null pointer exception.
Below is the model indicative of 1 row of the DB
public class Row
{
#EmbeddedId
private RowKey rowkey;
#Column
private String rowAttribute;
//getters and setters for rowkey and rowAttribute
}
Below is the model indicative of RowKey
public class RowKey
{
#Column(name = "rowBlock")
private String rowBlock;
#Column(name = "rowSection")
private String rowSection;
//getters and setters for above fields
}
I'm using QueryByExampleExecutor by extending my Repository(or DAO) with it as
public interface RowRepo extends CrudRepository<Row, RowKey>, QueryByExampleExecutor<Row> {
}
In my service layer I use the following statement to call repo methods to return a list of matched rows from DB
public List<Row> getRowRangeQuery(rowBlock,rowSection,rowAttribute)
{
Row row = new Row(new RowKey(rowBlock,rowSection),rowAttribute);
List<Row> Result = (List<Row>)getRowRepository().findAll(Example.of(row));
return Result;
}
I get an InvocationTargetException which when unrolled reveals a null pointer Exception at rowSection.

Related

Spring data mongo - unique random generated field

I'm using spring data mongo. I have a collection within a document that when I add an item to it I would like to assign a new automatically generated unique identifier to it e.g. (someGeneratedId)
#Document(collection = "questionnaire")
public class Questionnaire {
#Id
private String id;
#Field("answers")
private List<Answer> answers;
}
public class Answer {
private String someGeneratedId;
private String text;
}
I am aware I could use UUID.randomUUID() (wrapped in some kind of service) and set the value, I was just wondering if there was anything out of the box that can handle this? From here #Id seems to be specific to _id field in mongo:
The #Id annotation tells the mapper which property you want to use for
the MongoDB _id property
TIA
No there is no out of the box solution for generating ids for properties on embedded documents.
If you want to keep this away from your business-logic you could implement a BeforeConvertCallback which generates the id's for your embedded objects.
#Component
class BeforeConvertQuestionnaireCallback implements BeforeConvertCallback<Questionnaire> {
#Override
public Questionnaire onBeforeConvert(#NonNull Questionnaire entity, #NonNull String collection) {
for (var answer : entity.getAnswers()) {
if (answer.getId() == null) {
answer.setId(new ObjectId().toString());
}
}
return entity;
}
}
You could also implement this in a more generic manner:
Create a new annotation: #AutogeneratedId.
Then listen to all BeforeConvertCallback's of all entities and iterate through the properties with reflection. Each property annotated with the new annotation gets a unique id if null.

Advantage of assigning the returned savedEntity in Spring Data

I see in most of the coders save data(using spring data) as:
savedEntity = repo.save(savedEntity);
Long id = savedEntity.getId();
I am confused about why most of them assign back the returned value to the saved Entity while the following code also works exact(I have tested myself):
repo.save(savedEntity);
Long id = savedEntity.getId();
Did I miss some benefit of assigning back?
for example, let the entity be:
#Entity
public class SavedEntity {
#Id
private int id;
private String name;
//getter, setters, all arg-constructor, and no-arg constructor
}
Consider the object of SavedEntity is
SavedEntity entity = new SavedEntity(1,"abcd");
now for your first question,
SavedUser entity1 = repo.save(entity);
Long id = entity1.getId();
this entity1 object is the return object getting from the database, which means the above entity is saved in the database succesfully.
for the Second Question,
repo.save(entity);
Long id = entity.getId();//which you got it from SavedEntity entity = new SavedEntity(1,"abcd");
here the value of id is the integer you mentioned in place of id(the raw value).
Most of the time the id (primary key) is generated automatically while storing the entity to the database using strategies like AUTO, Sequence etc. So as to fetch those id's or autogenerated primary key values we assign back the saved entity.
For example:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
}
In this case you'll not pass the id externally but it will create a value for it automatically while storing the data to DB.

Spring Data JPA Projection with select distinct

I have a database table which holds Metadata for documents. My task now is to get a list with documenttypes. The documenttypes are not unique in the database table but of course I want them to be in my list. The sql is very simple:
SELECT DISTINCT groupname, group_displayorder
FROM t_doc_metadata
ORDER BY group_displayorder;
I have learned that I can use projections to get a subset of fields from my entity DocMetadata. I solved this as follows. My Entity:
#Entity
#Table(name="T_DOC_METADATA")
#Data
public class DocMetadata {
..............
#Column(nullable=false)
private String displayname;
#Column(nullable=false)
private Integer displayorder;
#Column(nullable=false)
private String groupname;
#Column(name="GROUP_DISPLAYORDER",
nullable=false)
private Integer groupDisplayorder;
#Column(name="METADATA_CHANGED_TS",
nullable=false,
columnDefinition="char")
private String metadataChangedTimestamp;
..........
}
My inteface for projection:
public interface GroupnameAndOrder {
String getGroupname();
Integer getGroupDisplayorder();
void setGroupname(String name);
void setGroupDisplayorder(int order);
}
Now I thought I'd be extraordinary clever by adding these lines to my repository:
#Query("select distinct d.groupname, d.groupDisplayorder from DocMetadata d order by d.groupDisplayorder")
public List<GroupnameAndOrder> findSortedGroupnames();
Sadly, when iterating over the result list and calling getGroupname() the result is null.
So I changed the lines in my repository according to the documentation:
public List<GroupnameAndOrder> findBy();
Now I get the groupnames but of course they are not unique now. So it doesn't solve my problem.
Is there any way to receive a ordered list with unique groupnames?
You are trying to be too clever. Instead just write the proper find method and return the GroupnameAndOrder. Spring Data JPA will then only retrieve what is needed for the projection.
Something like this should do the trick.
List<GroupnameAndOrder> findDistinctByOrderByGroupDisplayorder();

Retrieve the record using Spring Data JPA

I'm having spring data jpa repository.I the entity contain primary key id int and ipaddress string. The table contain only 1 record at a time otherwise null.
How do i retrieve the record using JPA , if it is not found return null.
#Repository
public interface IpConfigRepository extends JpaRepository<IpConfig, Integer> {
//
IpConfig findIpConfig();
}
According to the naming convention, you should define the method with the name findById(Integer id) ( assume the Id is the primary key )
Suppose you have a class A as shown below
class A{
private int id;
private String data;
// getters and setters
}
You can now search the items by the following ways.
public interface ARepo extends JpaRepository<A,Integer>{
// get all the records from table.
List<A> findAll();
// find record by id
A findById(int id);
// find record by data
A findByData(String data);
// find by date created or updated
A findByDateCreated(Date date);
// custom query method to select only one record from table
#Query("SELECT * FROM a limit 1;")
A findRecord();
}

Implementation of One-to-Many Relationships with Document References using mongodb and spring data

I want to use spring data with mongodb and want to implement a one to many relationship using document reference.
db should look like this:
{
_id = 123451232
"countryName":"India",
"status":"true",
"meetings":[123451233, 123451234]
}
{
_id = 123451233
"countryName":"china",
"status":"true"
}
{
_id = 123451234
"countryName":"china",
"status":"true"
}
TO achieve this i used dbRef
country model
#Document(collection = "country")
public class Country {
#Id
#Field("country_id")
private String countryId;
#Field("country_name")
#Indexed
private String countryName;
#Field("status")
private boolean status = true;
#DBRef
private List<Country> meetings= new ArrayList<Country>();
// getters and setters
i got an error
HTTP Status 500 - Request processing failed; nested exception is org.springframework.data.mapping.model.MappingException: Cannot create a reference to an object with a NULL id.

Resources