Why is Spring Cassandra not using the Values set in #Table with Scala? - spring

I have the following code...
#Table(keyspace = "ks", name="otherThing" )
class Thing extends Serializable{
...
}
However when I run...
repo.findAll()
I get an error that looks like it isn't using the values I provided...
Query; CQL [SELECT * FROM Thing;]; unconfigured table Thing
I would expect
Select * from ks.otherThing;
What am I missing?
Update
I tried converting to the following Pojo
import com.datastax.driver.mapping.annotations.Table;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
#Table( keyspace="ks", name="otherThing" )
public class Thing implements Serializable {
...
}
And my repo is pretty simple...
import org.springframework.stereotype.Repository;
#Repository
public interface ThingRepository extends CassandraRepository<Thing, ThingId> { }
but
thingRepo.findAll();
gives...
Query; CQL [SELECT * FROM thing;]; unconfigured table thing

So the mistake I made was trying to do this with a connection that was set up using my company's spring autoconfig. This allowed me to configure the connection via application.properties. I noticed that the keyspace was previously declared there so I went back and changed my domain object to...
import org.springframework.data.cassandra.core.mapping.Table
#Table("otherThing" )
class Thing extends Serializable{
...
}
Now it is working. Leaving this answer up in case others get confused.

Related

Spring Boot JPA Query modify dynamically

Using Spring boot,I am working on one business use case where i need to modify the JPA query generated at runtime based on configuration.
For Example .. if query that JPA generates is
select * from customers where id=1234
I want to modify it in runtime like based on user's logged in context. (Context has one attribute business unit) like given below ..
select * from customers where id=1234 and ***business_unit='BU001'***
Due to certain business use case restrictions i can't have statically typed query.
Using Spring boot and Postgres SQL.
Try JPA criteria builder , it let you to create dynamics query programmatically.
Take look in this post
What is stopping you to extract the business unit from the context and pass it to the query?
If you have this Entity
#Entity
CustomerEntity {
Long id;
String businessUnit;
//geters + setters
}
you can add this query to your JPA Repository interface:
CustomerEntity findByIdAndBusinessUnit(Long id, String businessUnit)
This will generate the following "where" clause:
… where x.id=?1 and x.businessUnit=?2
for complete documentation check Spring Data Jpa Query creation guide.
you would do something like this, this lets you dynamically define additional predicates you need in your query. if you don't want to have all the conditions in your query with #Query
The below example just adds a single predicate.
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import study.spring.data.jpa.models.TicketPrice;
#Component
public class TricketPriceCriteriaRepository {
#Autowired
TicketPriceJpaRepository ticketPriceJpaRepository;
public List<TicketPrice> findByCriteria(int price) {
return ticketPriceJpaRepository.findAll(new Specification<TicketPrice>() {
#Override
public Predicate toPredicate(Root<TicketPrice> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if (price > 0) {
predicates.add(
criteriaBuilder.and(criteriaBuilder.greaterThan(root.get("basePrice"), price)));
}
// Add other predicates here based on your inputs
// Your session based predicate
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
});
}
}
Your base repository would be like
// Other imports
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface TicketPriceJpaRepository
extends JpaRepository<TicketPrice, Long>, JpaSpecificationExecutor<TicketPrice> {}
the model consists basePrice
#Column(name = "base_price")
private BigDecimal basePrice;

Getting aggregate data from table

I want to get aggregate data from a table using spring data.
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryEntity> getSummary(#Param("groupId" Long groupId));
package com.refinitiv.eit.kv.label.enity.response;
import lombok.AllArgsConstructor;
import lombok.Data;
#Data
#AllArgsConstructor
public class SummaryResponse {
#Column("TOTAL_1")
private Double total_1;
#Column("MAX_1")
private Double max_1;
}
However I get this error : "Could not read property #org.springframework.data.annotation.Id() " ...
There should be no ID, only a single row with the summary data.
Any ideas on getting the summary data?
(the code is more complex but cleared up for this)
First of all, if you need your entity SummaryResponse to be managed by JPA and eventually persist it, you need to annotate it as #Entity and assign it either id or composite id (annotated with #Id).
If you just want to use that DTO for fetching the data, you can use a Spring's interface based projection for that:
public interface SummaryResponseProjection{
getTotal1();
getMax1();
}
and then use it for mapping the results of the query:
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryResponseProjection> getSummary(#Param("groupId" Long groupId));
Found the reason:
This method was part of a repository defined as ReactiveCrudRepository<RawEntity, Long>, with RawEntity having the id defined.
Moving the method into a new repo defined as ReactiveCrudRepository<SummaryEntity, Void> solves the issue.
Thanks all!

Spring Boot repository save does not work (only shows a select)

I'm facing for hours with a strange proceeding in Spring Boot when try to save a mapped entity.
The entity class with a composite key that must all be set by the user is as follows:
package model
import javax.persistence.*
#Entity
#Table(name = 'MY_TABLE')
#IdClass(MyIdClass.class)
class MyClass implements Serializable{
#Id
#Column(name = "MY_COLUMN_1")
Long column1
#Id
#Column(name = "MY_COLUMN_2")
Long column2
#Id
#Column(name = "MY_COLUMN_3")
String column3
#Id
#Column(name = "MY_COLUMN_4")
Date date1
#Column(name = "MY_COLUMN_5")
Date date2
#Column(name = "MY_COLUMN_6")
BigDecimal column6
}
#Embeddable
class MyIdClass implements Serializable{
Long column1
Long column2
String column3
Date date1;
}
The corresponding repository is:
package repository
import org.springframework.data.repository.CrudRepository
interface MyRepository extends CrudRepository<MyClass, Long>{
}
My service is:
package service
import model.MyClass
import repository.MyRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
#Service
class MyService {
#Autowired
MyRepository repository
void save(MyClass myClass) {
repository.save(myClass)
}
}
My controller mounts a MyClass object with all data set, including the composite key. When it calls the service save method the object is not inserted in the database. I saw the logs and checked that there is a SELECT in MY_TABLE instead of INSERT. I tried not to inform the composite key in the object and then the save method did an INSERT with error due to null values in the primary key.
I really don't understand why the insertion is not done when the composite key has values. How can I solve it?
I've already tried with #Transactional in service class and didn't work. I didn't do any Transaction configuration in the project since Spring Boot delivers it as default.
Thanks.
It seems you are using MyIdClass as the Id for MyClass. So, the Repository should be:
interface MyRepository extends CrudRepository<MyClass, MyIdClass>{
}
Hope this help.
I take your code sample and tried it on a sample Spring Boot project, where I was able to save to H2 DB (In memory) with #Embeddable & #EmbeddedId annotations. If you would like to verify, you can clone the GitHub repo and run the BootJpaApplication.java as a Java Application.
After execution access the H2 console with the below link from local where table details can be verified.
http://localhost:8080/h2-console
https://github.com/sujittripathy/springboot-sample.git
Hope the detail helps:)

Spring Data JPA native query result binding

Entity class:
#Entity
#SqlResultSetMapping(
name="hourMapping",
classes=#ConstructorResult(
targetClass=Representation.class,
columns={
#ColumnResult(name="hour", type=BigDecimal.class),
#ColumnResult(name="transactions", type=BigDecimal.class)
}
)
)
#NamedNativeQuery(name="MyEntity.reportByHour", query="SELECT hour,SUM(tran_per_hour) AS transactions FROM MY_ENTITY GROUP BY hour ORDER BY hour"
,resultSetMapping="hourMapping")
#Table(name="MY_ENTITY")
public class MyEntity implements Serializable {
Pojo class:
#Data //Lombok
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class Representation {
public Representation(BigDecimal hour, BigDecimal transactions) {
this.hour = hour;
this.transactions = transactions;
}
private BigDecimal hour;
private BigDecimal transactions;
Repository interface:
public interface MyEntityRepository extends JpaRepository<MyEntity, MyEntityPK> {
List<Representation> reportByHour();
}
When I run the endpoint which invokes the native query, I get exception:
Failed to convert from type [java.lang.Object[]] to type [com.representation.Representation] for value '{0, 198}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.math.BigDecimal] to type [com.representation.Representation]
Now if I just have "hour" field returned from my native query (and relevant changes to POJO constructor etc) it works fine.
Any help appreciated.
Ok, false alarm. My hibernate dependencies were all messed up and causing conflicts so resulting in the above exception.
After fixing these dependency issues, works great!!
Long story short: let spring-boot-* handle most hibernate dependencies instead of overriding or managing your own.

Could not execute JDBC batch update

I have a problem with a entity class. When I run my app with hibernate.hbm2ddl.auto = create, then it create all the other entity tables but not this on. Why is that? And when I create the table by myself and after that try to insert something into it, then I get this error: http://pastebin.com/m4gjxqNC
Here's my entity class:
User entity:
http://pastebin.com/YXvzFSgt
Comment entity:
http://pastebin.com/RpZEUPxN
And here's the UserDAO class
http://pastebin.com/LrTCg0GC
You seems to be using PostgreSQL. As per this document, 'User' is a PostgreSQL reserved word. Try adding a #Table("user_tb") annotation for your User entity, to force a new table name.
#Entity
#Table("user_tb")
public class User extends LightEntity implements Serializable {
//..
}

Resources