invoking oracle stored procedure with List of objects - java

I have an oracle package with procedure
TYPE rpa_type IS RECORD (
OPNAME RPA_SUMMARY_AUDIT.OPNAME%TYPE,
PROCESSDATE RPA_SUMMARY_AUDIT.PROCESSDATE%TYPE,
SESSIONID RPA_SUMMARY_AUDIT.SESSIONID%TYPE,
TOTALCOUNT RPA_SUMMARY_AUDIT.TOTALCOUNT%TYPE,
SUCCESSCOUNT RPA_SUMMARY_AUDIT.SUCCESSCOUNT%TYPE,
FAILEDCOUNT RPA_SUMMARY_AUDIT.FAILEDCOUNT%TYPE
);
TYPE rpa_tab IS TABLE OF rpa_type INDEX BY BINARY_INTEGER;
PROCEDURE save_rpa_summary(
p_parm IN rpa_tab,
p_affiliate_code IN VARCHAR);
and descirption
PROCEDURE save_rpa_summary(
p_parm IN rpa_tab,
p_affiliate_code IN VARCHAR
) IS
p_response_code VARCHAR(500);
ver_count NUMBER;
BEGIN
SELECT 'toto' INTO p_response_code FROM dual;
FOR i IN p_parm.first .. p_parm.last
LOOP
--
INSERT INTO RPA_SUMMARY_AUDIT
(ID, OPNAME, PROCESSDATE, SESSIONID, TOTALCOUNT, SUCCESSCOUNT, FAILEDCOUNT, AFFILIATE, CRATEDDATE)
VALUES(RPA_SUMMARY_AUDIT_SEQ.nextval, p_parm(i).OPNAME, p_parm(i).PROCESSDATE, p_parm(i).SESSIONID, p_parm(i).TOTALCOUNT, p_parm(i).SUCCESSCOUNT, p_parm(i).FAILEDCOUNT, p_affiliate_code, CURRENT_DATE);
ver_count:=ver_count+1;
END LOOP;
p_response_code:=ver_count;
dbms_output.put_line(p_response_code);
EXCEPTION
WHEN PROGRAM_ERROR THEN
dbms_output.put_line('ID must be greater than zero!');
p_response_code:=-1;
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
p_response_code:=-1;
WHEN others THEN
dbms_output.put_line('Error!');
p_response_code:=-1;
END save_rpa_summary;
i can invoke it using test it using
DECLARE
v_t VARCHAR(255);
t_rpa test_pkg.rpa_tab;
BEGIN
t_rpa(1).OPNAME := 'process 1';
t_rpa(1).PROCESSDATE := 'Dec-12-2019';
t_rpa(1).SESSIONID := null;
t_rpa(1).TOTALCOUNT :=3000;
t_rpa(1).SUCCESSCOUNT :=2500;
t_rpa(1).SUCCESSCOUNT :=500;
t_rpa(2).OPNAME := 'process 2';
t_rpa(2).PROCESSDATE := 'Dec-12-2019';
t_rpa(2).SESSIONID := 'SESSION 1';
t_rpa(2).TOTALCOUNT :=2500;
t_rpa(2).SUCCESSCOUNT :=1350;
t_rpa(2).SUCCESSCOUNT :=null;
TEST_PKG.SAVE_RPA_SUMMARY(t_rpa,'ENG');
END;
i am trying to use spring data jpa to invoke this procedure or SimpleJdbcCall
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import java.io.Serializable;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class RpaDbProcessingSumarry implements Serializable {
private static final long serialVersionUID = 1L;
private String opName ;
private String processDate;
private String sessionId;
private Long totalCount ;
private Long successCount ;
private Long failedCount ;
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Entity(name = "RPASUMMARYAUDIT")
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(name = "SAVE_RPA_SUMMARY",
procedureName = "MMHUSER.TEST_PKG.SAVE_RPA_SUMMARY",
parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "p_parm", type = RpaDbProcessingSumarry[].class),
#StoredProcedureParameter(mode = ParameterMode.IN, name = "p_affiliate_code", type = String.class)
})
})
public class RpaProcessProcessSummary {
#Id
private Long id;
private String name;
private String prccessDate;
private String session;
private Long totalCount;
private Long successCount;
private Long failedCount;
}
#Repository
public interface RpaProcessProcessSummaryRepositary extends CrudRepository<RpaProcessProcessSummary, Long> {
#Transactional(propagation = Propagation.REQUIRED,readOnly = false)
#Procedure(name = "SAVE_RPA_SUMMARY")
void saveRpaSummaryData( RpaDbProcessingSumarry[] p_parm, String p_affiliate_code);
}
public void call(RpaDbProcessingSumarry[] p_parm ) {
SqlParameterSource in = new MapSqlParameterSource().addValue("p_parm", p_parm).addValue("p_affiliate_code","eng");
Map<String, Object> execute = new SimpleJdbcCall(this.jdbcTemplate).withCatalogName("MMHUSER")
.withProcedureName("TEST_PKG.SAVE_RPA_SUMMARY")
.execute(in);
in both cases i am getting exception
PLS-00306: wrong number or types of arguments in call to 'SAVE_RPA_SUMMARY'
ORA-06550: line 1, column 7:
is there a way to invoke this stored procedure from spring in any way

Related

repository.save function changes id of it's children entity

I'm trying to update existing entry in parent Entity and I encounter error I can't understand nor resolve.
I have two entities in a simple crud repository - Parent(User) and Children(movie). I am trying to pass a favourite movie to an user. The goal is that the movie doesn't have to be already in database, and the #PostMapping has to accept an user_id and movie name as parameters, other method uses the movie name, goes through the OMDBapi, parses data from json to fields and then gives the user at user_id the movie as a favourite. The PostMapping sort of works, because it gets the user at user_id, the movie is also added, but when the url looks like this - http://localhost:8080/users/2/fight+club the user at user_id 2 gets the movie as his favourite, but the movie gets it's id also as 2, even if it's first movie being added to repository. What I don't understand is why when I try to debug this every line of code is acting as I expect it to do -
wUser(id=2, name=Jan, favouriteMovies=[Movie(id=1, title=Fight Club, plot=An insomniac office worker and a devil-may-care soap maker form an underground fight club that evolves into much more., genre=Drama, director=David Fincher, posterURL=https://m.media-amazon.com/images/M/MV5BNDIzNDU0YzEtYzE5Ni00ZjlkLTk5ZjgtNjM3NWE4YzA3Nzk3XkEyXkFqcGdeQXVyMjUzOTY1NTc#._V1_SX300.jpg)])
but after it passes repository.save(user) line I get redirected to InvocableHandlerMethod class, into doInvoke method, into
return KotlinDetector.isSuspendingFunction(method) ? this.invokeSuspendingFunction(method, this.getBean(), args) : method.invoke(this.getBean(), args);
this line, and after that it's just deep into the rabbit hole. As I am quite an inexperienced in coding in Java, what probably can be deducted, I don't really understand nor can find solution to this problem.
The entities and controller classes below
package com.example.omdbapirest.movie;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="movie_id")
private Integer id;
private String title;
private String plot;
private String genre;
private String director;
private String posterURL;
public Movie(String title, String plot, String genre, String director, String posterURL) {
this.title = title;
this.plot = plot;
this.genre = genre;
this.director = director;
this.posterURL = posterURL;
}
}
package com.example.omdbapirest.user;
import com.example.omdbapirest.movie.Movie;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
#Data
#Entity
#NoArgsConstructor
#AllArgsConstructor
public class wUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
// #OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH})
#OneToMany(cascade =CascadeType.ALL)
#JoinColumn(name = "movie_id")
private List<Movie> favouriteMovies;
public wUser(String name) {
this.name = name;
}
}
UserController
package com.example.omdbapirest.user;
import com.example.omdbapirest.movie.Movie;
import com.example.omdbapirest.movie.MovieService;
import lombok.RequiredArgsConstructor;
import org.json.simple.parser.ParseException;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
#RestController
#RequestMapping("/users")
#RequiredArgsConstructor
public class UserController {
private final MovieService movieService;
private final UserRepository repository;
private final UserService service;
#GetMapping
public List<wUser> getUsers(){
return repository.findAll();
}
#PostMapping("/{id}/{moviename}")
public void addMovieAsFavorite (#PathVariable (name= "id") int id,
#PathVariable (name="moviename") String moviename)
throws ParseException{
String url = "https://www.omdbapi.com/?t="+moviename+"&apikey=30ccf40c";
wUser user = repository.getById(id);
List<Movie> movies = user.getFavouriteMovies();
List<Movie>moviesToAdd = new ArrayList<>();
Movie movie = movieService.getDataFromOMDBAsMovie(url);
movies.add(movie);
moviesToAdd.addAll(movies);
user.setFavouriteMovies(moviesToAdd);
repository.save(user);
}
}
I'm also adding MovieService class in case there is some error in the JSON parser
package com.example.omdbapirest.movie;
import lombok.RequiredArgsConstructor;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
#Service
#RequiredArgsConstructor
public class MovieService {
private final MovieRepository repository;
public String getJSONFromURL(String strUrl) {
String jsonText = "";
try {
URL url = new URL(strUrl);
InputStream is = url.openStream();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(is));
String line;
while ((line = bufferedReader.readLine()) != null) {
jsonText += line + "\n";
}
is.close();
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
return jsonText;
}
public Movie getDataFromOMDBAsMovie(String strURL) throws ParseException {
String json = getJSONFromURL(strURL);
Movie movie = new Movie();
JSONParser parser = new JSONParser();
Object object = parser.parse(json);
JSONObject mainJsonObject = (JSONObject) object;
String title = (String)mainJsonObject.get("Title");
movie.setTitle(title);
String plot = (String)mainJsonObject.get("Plot");
movie.setPlot(plot);
String genre = (String)mainJsonObject.get("Genre");
movie.setGenre(genre);
String director = (String)mainJsonObject.get("Director");
movie.setDirector(director);
String posterURL = (String)mainJsonObject.get("Poster");
movie.setPosterURL(posterURL);
repository.save(movie);
return movie;
}
public Movie addMovie(Movie movie){
return repository.save(movie);
}
}
I tried adding movies to db, reworking the favourite saving class, all to no avail, I was getting different errors when not debuging, including
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Pole nie może być NULL"MOVIE_ID"(Field cannot be NULL)
NULL not allowed for column "MOVIE_ID"; SQL statement:
update movie set movie_id=null where movie_id=? [23502-214]
and
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Naruszenie ograniczenia Klucza Głównego lub Indeksu Unikalnego: "PRIMARY KEY ON PUBLIC.MOVIE(MOVIE_ID)(translating to- Unique Index or primary key violated)
( /* key:2 */ 2, 'David Fincher', 'Drama', 'An insomniac office worker and a devil-may-care soap maker form an underground fight club that evolves into much more.', 'https://m.media-amazon.com/images/M/MV5BNDIzNDU0YzEtYzE5Ni00ZjlkLTk5ZjgtNjM3NWE4YzA3Nzk3XkEyXkFqcGdeQXVyMjUzOTY1NTc#._V1_SX300.jpg', 'Fight Club')"
Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.MOVIE(MOVIE_ID) ( /* key:2 */ 2, 'David Fincher', 'Drama', 'An insomniac office worker and a devil-may-care soap maker form an underground fight club that evolves into much more.', 'https://m.media-amazon.com/images/M/MV5BNDIzNDU0YzEtYzE5Ni00ZjlkLTk5ZjgtNjM3NWE4YzA3Nzk3XkEyXkFqcGdeQXVyMjUzOTY1NTc#._V1_SX300.jpg', 'Fight Club')"; SQL statement:
insert into movie (director, genre, plot, posterurl, title, movie_id) values (?, ?, ?, ?, ?, ?) [23505-214]
Both of these errors appear when I try to add another movie to given user, I mean I was able to give all users 1 movie, but never more since it tries to always add the movie with id of the user
Let's focus on the relevant part of your mapping:
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="movie_id")
private Integer id;
}
and
public class wUser {
#OneToMany(cascade =CascadeType.ALL)
#JoinColumn(name = "movie_id")
private List<Movie> favouriteMovies;
}
The id property of Movie is mapped to the table column movie_id by the configuration in the Movie class.
But for the wUser.favouriteMovies you use #JoinColumn to make it use movie_id the join column, i.e. the column in the Movie table that references the wUser.
By this that column is mapped to two completely different values and it seems in your scenario the second one wins.
To fix this simply choose a different column for the join column. user_id might be a good choice.

Save List as JSON array in postgresql

I have a List private List<Lesson> lessons; and I need to save this list to PostgreSQL database column with data type _json or json[] (JSON array). But I get one of these errors:
ERROR: column "lessons" is of type json[] but the expression is of
type character varyingorERROR: malformed array literal:
"[{"id":17,"title":"Lesson 1","part":1.0}]
How correctly serialize List to get the correct format of Postgresql JSON array?
You might need to use JsonBinaryType class from com.vladmihalcea:hibernate-types library and apply json (or jsonb) to the column definition:
// LessonList.java
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
#Entity
#Table(name = "lessons")
#Getter
#Setter
#Builder
#AllArgsConstructor
#NoArgsConstructor
#TypeDef(name = "json", typeClass = JsonBinaryType.class)
public class LessonList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Type(type = "json")
#Column(columnDefinition = "json")
private List<Lesson> lessons;
}
SQL Script to create the table:
CREATE TABLE "lessons" (
"id" Serial NOT NULL,
"lessons" JSON NOT NULL,
"created_at" Timestamp Without Time Zone DEFAULT NOW() NOT NULL,
PRIMARY KEY ("id")
);
The rest of the classes are to provide working example:
// Lesson.java
#Getter
#Setter
#Builder
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class Lesson {
private int id;
private String title;
private double part;
}
A repository extending Spring CrudRepository interface and DAO class are trivial.
A command line runner to run test:
#Slf4j
#Component
public class TestJson implements CommandLineRunner {
#Autowired
private LessonListDao dao;
#Override
public void run(String[] args) {
List<Lesson> lessons = Arrays.asList(
Lesson.builder().id(11).title("Physics").part(1.0).build(),
Lesson.builder().id(12).title("Chemistry").part(2.0).build(),
Lesson.builder().id(13).title("Biology").part(3.0).build()
);
LessonList list = LessonList.builder().lessons(lessons).build();
LessonList result = dao.save(list);
LOGGER.info("result: " + result);
List<LessonList> all = dao.findAll();
all.forEach(a -> LOGGER.info("item #" + a.getId() + "; lessons=" + a.getLessons()));
}
}
Output:
lesson.TestJson : result: lesson.LessonList#6166aac5
lesson.TestJson : item #1; lessons=[Lesson(id=1, title=Math, part=1.0), Lesson(id=2, title=English, part=2.0), Lesson(id=3, title=Informatics, part=3.0)]
lesson.TestJson : item #2; lessons=[Lesson(id=11, title=Physics, part=1.0), Lesson(id=12, title=Chemistry, part=2.0), Lesson(id=13, title=Biology, part=3.0)]
DB Data: SELECT * FROM "public".lessons:
**id** **lessons** **created_at**
[PK] Integer json timestamp without timezone
1 [{"id":1,"title":"Math","part":1.0}, 2020-06-03 18:08:55.948007
{"id":2,"title":"English","part":2.0},
{"id":3,"title":"Informatics","part":3.0}]
2 [{"id":11,"title":"Physics","part":1.0}, 2020-06-03 18:27:06.565191
{"id":12,"title":"Chemistry","part":2.0},
{"id":13,"title":"Biology","part":3.0}]
Update
This library does not support json[] type because it could be rather redundant.
The example below uses plain JDBC + ObjectMapper to handle specific PostgreSQL array of json
Main point is that you need to use getArray method of ResultSet and then convert the String values inside PGobject to your object
ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();
DataSource ds = DataSourceBuilder.create()
.username(environment.getProperty("ds.pgsql.username"))
.password(environment.getProperty("ds.pgsql.password"))
.url(environment.getProperty("ds.pgsql.url")).build();
try (Connection connection = ds.getConnection();
PreparedStatement ps = connection.prepareStatement("SELECT id, lessons FROM lesson");
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("id");
Object[] arrLessons = (Object[]) rs.getArray("lessons").getArray();
List<Lesson> jsonLessons = Arrays.stream(arrLessons)
.map(PGobject.class::cast)
.map(lesson -> convert(lesson.getValue()))
.collect(Collectors.toList());
System.out.println(id + "; converted: " + jsonLessons);
}
}
//...
private Lesson convert(String value) {
try {
return mapper.readValue(value, Lesson.class);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
}
Output
1; converted: [Lesson(id=1, title=Math, part=0.0), Lesson(id=2, title=English, part=0.0)]
2; converted: [Lesson(id=3, title=Physics, part=0.0), Lesson(id=4, title=Chemistry, part=0.0)]

Retrieving java objects list rather than requested objects list from database

I have a problem while I'm trying to pull data from my DB requesting to be in a specific object type. I've created query, which is fetching objects of Java Object type not the type that I need. Here is my DAO class:
import com.jackowiak.Domain.TurbinesData;
import com.jackowiak.Model.TurbineDataCSVReader;
import com.jackowiak.Utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import java.util.List;
public class TurbinesDaoBean {
private static final Logger LOG = LoggerFactory.getLogger(TurbinesDaoBean.class);
public List<TurbinesData> getTurbineDataFromDB(String turbineName) {
LOG.info("Initializating DB connection to get turbine data");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Query query = session.createQuery("select windSpeed, turbinePower from TurbinesData where turbineName = :turbineName");
query.setParameter("turbineName", turbineName);
session.getTransaction().commit();
List<TurbinesData> results = query.list();
LOG.debug("Data for turbine " + turbineName + " collected successfully");
return results;
}
}
And here is my Entity class:
#Entity
#Table(name = "TurbinesData")
public class TurbinesData {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
protected long id;
#Column(nullable = false, length = 50, name = "Nazwa_turbiny")
protected String turbineName;
#Column(nullable = false, length = 20, name = "V_wiatru")
protected Double windSpeed;
#Column(nullable = false, length = 20, name = "Moc_turbiny")
protected Double turbinePower;
public TurbinesData() {
}
public TurbinesData(Double windSpeed, Double turbinePower) {
this.windSpeed = windSpeed;
this.turbinePower = turbinePower;
}
public TurbinesData(String turbineName, Double windSpeed, Double turbinePower) {
this.turbineName = turbineName;
this.windSpeed = windSpeed;
this.turbinePower = turbinePower;
}
// getters and setters
}
I would like to receive list of TurbinesData objects after executing query
Change the jpql to:
"FROM TurbinesData td WHERE td.turbineName = :turbineName"
And then use TypedQuery
EDIT:
According to your comment you want to retrieve only two fields. You need to do:
"SELECT NEW package.to.TurbinesData(td.windSpeed, td.turbinePower) FROM TurbinesData td WHERE td.turbineName = :turbineName"
Note:
Need to have proper constructor defined.
Need to use fully qualified name
You can typecast List<Object> to List<custom class>
Like.
return (List<T>) query.list();
Hope that helps.

how to join two tables and get all matched record in hibernate(using entity class mapping)

I have two entities called FeeTerms.java and FeeTermDates.java
I want to get all matched records from these two entities using pure HQL
Look at entities:
FeeTerms.java
package com.rasvek.cg.entity;
// Generated May 14, 2018 11:39:07 PM by Hibernate Tools 5.1.7.Final
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* FeeTerms generated by hbm2java
*/
#Entity
#Table(name = "fee_terms", catalog = "campus_guru_01")
public class FeeTerms implements java.io.Serializable {
private Integer termId;
private String termName;
private String termCount;
private Set<FeeTermDates> feeTermDateses = new HashSet<FeeTermDates>(0);
private Set<AssocFeeTerms> assocFeeTermses = new HashSet<AssocFeeTerms>(0);
public FeeTerms() {
}
public FeeTerms(String termName, String termCount, Set<FeeTermDates> feeTermDateses,
Set<AssocFeeTerms> assocFeeTermses) {
this.termName = termName;
this.termCount = termCount;
this.feeTermDateses = feeTermDateses;
this.assocFeeTermses = assocFeeTermses;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "term_id", unique = true, nullable = false)
public Integer getTermId() {
return this.termId;
}
public void setTermId(Integer termId) {
this.termId = termId;
}
#Column(name = "term_name")
public String getTermName() {
return this.termName;
}
public void setTermName(String termName) {
this.termName = termName;
}
#Column(name = "term_count", length = 45)
public String getTermCount() {
return this.termCount;
}
public void setTermCount(String termCount) {
this.termCount = termCount;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "feeTerms")
public Set<FeeTermDates> getFeeTermDateses() {
return this.feeTermDateses;
}
public void setFeeTermDateses(Set<FeeTermDates> feeTermDateses) {
this.feeTermDateses = feeTermDateses;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "feeTerms")
public Set<AssocFeeTerms> getAssocFeeTermses() {
return this.assocFeeTermses;
}
public void setAssocFeeTermses(Set<AssocFeeTerms> assocFeeTermses) {
this.assocFeeTermses = assocFeeTermses;
}
}
FeeTermDates.java
package com.rasvek.cg.entity;
// Generated May 14, 2018 11:39:07 PM by Hibernate Tools 5.1.7.Final
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* FeeTermDates generated by hbm2java
*/
#Entity
#Table(name = "fee_term_dates", catalog = "campus_guru_01")
public class FeeTermDates implements java.io.Serializable {
private int tdmId;
private FeeTerms feeTerms;
private String date;
public FeeTermDates() {
}
public FeeTermDates(int tdmId, FeeTerms feeTerms) {
this.tdmId = tdmId;
this.feeTerms = feeTerms;
}
public FeeTermDates(int tdmId, FeeTerms feeTerms, String date) {
this.tdmId = tdmId;
this.feeTerms = feeTerms;
this.date = date;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "tdm_id", unique = true, nullable = false)
public int getTdmId() {
return this.tdmId;
}
public void setTdmId(int tdmId) {
this.tdmId = tdmId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "term_id", nullable = false)
public FeeTerms getFeeTerms() {
return this.feeTerms;
}
public void setFeeTerms(FeeTerms feeTerms) {
this.feeTerms = feeTerms;
}
#Column(name = "date")
public String getDate() {
return this.date;
}
public void setDate(String date) {
this.date = date;
}
}
i have tried with following code but i am not getting it
String hql="select FT.termId , FT.termName , FT.termCount,FT.feeTermDateses from FeeTerms FT ,FeeTermDates FD where FT.termId=FD.feeTerms" ;
query = currentSession.createQuery(hql);
termDatesList= query.getResultList();
how to achieve it as pure HQL. i am very new to Hibernate and HQl.
i have got something like below in another post,
public List<Category> getCategoryList(int id) {
List<Category> groupList;
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("select c from Category c join fetch c.events where c.parentCategory.categoryId = 1");
//query.setParameter("id", id);
groupList = query.list();
return groupList;
}
Is it possible to achieve my query as above done?
You can receive a list of Object[] with the values that you want. Like:
String hql="select FT.termId , FT.termName , FT.termCount, FT.feeTermDateses from FeeTerms FT, FeeTermDates FD where FT.termId = FD.feeTerms.id";
Query query = currentSession.createQuery(hql);
List<Object[]> results = query.getResultList();
for (Object[] obj : results) {
Integer termId = obj[0];
String termName = obj[1];
String termCount = obj[2];
Set<FeeTermDates> feeTermDates = obj[4];
}
But, I could suggest a better version:
String hql = "SELECT ft FROM FeeTerms ft JOIN ft.feeTermDateses feeTermDateses";
Query query = currentSession.createQuery(hql);
List<FeeTerms> results = query.getResultList();
This already brings to you all FeeTerms that have FeeTermDates.

About an exception org.springframework.core.convert.ConverterNotFoundException in spring-data-cassandra when i try to insert a row

i am quite newwbee with spring-data-cassandra and i am facing problems when i try to create one row within a cassandra table.
This is the exception when i try to run the test, setUp method is never executed:
org.springframework.core.convert.ConversionFailedException: **Failed to convert from type [java.util.HashSet<?>] to type [java.lang.String] for value '[unicon.matthews.entity.DataSync#79135a38[**
id=data_sync_id
orgId=identifier
tenantId=_tenand_id
syncDateTime=2017-09-25T13:35:14.153
syncType=all
syncStatus=fully_completed
]]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [unicon.matthews.entity.DataSync] to type [java.lang.String]
...
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [unicon.matthews.entity.DataSync] to type [java.lang.String]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
at org.springframework.core.convert.support.CollectionToStringConverter.convert(CollectionToStringConverter.java:71)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
... 60 more
This is the test:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = unicon.matthews.oneroster.service.repository.CassandraConfiguration.class)
public class CassandraOrgRepositoryTests {
final String _userName = UUID.randomUUID().toString();
final String _orgName = UUID.randomUUID().toString();
final String _sourceId = UUID.randomUUID().toString();
final String _id = UUID.randomUUID().toString();
final String _api_key = UUID.randomUUID().toString();
final String _api_secret = UUID.randomUUID().toString();
final String _tenant_id = "_tenand_id";
final Status _status = Status.inactive;
final OrgType _org_type = OrgType.school;
final String _org_identifier = UUID.randomUUID().toString();
#ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost().atLeast(Version.parse("3.0"));
#Autowired CassandraOrgRepository repository;
#Before
public void setUp() throws Exception {
repository.deleteAll();
OrgCassandraTable aPojo = new OrgCassandraTable();
aPojo.setTenantId(_tenant_id );
Org.Builder myOrgBuilder = Org.Builder.class.newInstance();
Map<String, String> metadata = new TreeMap<String,String>();
metadata.put("key","value");
Org myOrgPojo = myOrgBuilder.withIdentifier("identifier")
.withDateLastModified(LocalDateTime.now())
.withMetadata(metadata)
.withName(_orgName)
.withSourcedId(_sourceId)
.withStatus(_status)
.withType(_org_type)
.build();
aPojo.setSourcedId(_sourceId);
// active 0,
// inactive 1,
// tobedeleted 2;
aPojo.setStatus("1");
aPojo.setDateLastModified(LocalDateTime.now() );
aPojo.setName(_orgName);
aPojo.setType(_org_type.toString());
aPojo.setIdentifier(_org_identifier);
aPojo.setTenantId(_tenant_id);
// THIS MUST BE THE PROBLEM!
Set<DataSync> _dataSyncSet = new HashSet<DataSync>();
DataSync.Builder _dataSyncBuilder = DataSync.Builder.class.newInstance();
DataSync new_data_sync=_dataSyncBuilder.withId("data_sync_id")
.withOrgId(myOrgPojo.getIdentifier())
.withSyncDateTime(LocalDateTime.now())
.withSyncStatus(DataSync.DataSyncStatus.fully_completed)
.withSyncType(DataSync.DataSyncType.all)
.withTenantId(_tenant_id)
.build();
_dataSyncSet.add(new_data_sync);
aPojo.setDataSyncs(_dataSyncSet);
aPojo.setApiSecret(_api_secret);
aPojo.setApiKey(_api_key);
aPojo.setId(_id);
repository.save(aPojo);
assertTrue(repository.count() > 0);
System.out.println("Created a org with fake data...");
}
#Test
public void testFindbyId() {
Optional<WrapperOrg> loaded = repository.findById(_id);
Assert.assertNotNull(loaded);
Assert.assertEquals("something went wrong...",_id,loaded.get().getId());
}
}
This is the repository:
import java.util.Optional;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
// this repo must implement something that paginates rows, because ALLOW FILTERING must not be used
public interface CassandraOrgRepository extends CassandraRepository<OrgCassandraTable> {
#Query("SELECT * FROM org WHERE id = ?0")
Optional<WrapperOrg> findById(final String id);
#Query("SELECT * FROM org WHERE api_key = ?0 AND api_secret = ?1 ALLOW FILTERING")
Optional<WrapperOrg> findByApiKeyAndApiSecret(final String apiKey, final String apiSecret);
#Query("SELECT * FROM org WHERE api_key = ?0 ALLOW FILTERING")
Optional<WrapperOrg> findByApiKey(final String apiKey);
}
This is the CassandraConfiguration class that i mention in the test class. I suspect that i will have to do something here:
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
#Configuration
#EnableAutoConfiguration
public class CassandraConfiguration {
#Configuration
#EnableCassandraRepositories
static class CassandraConfig extends AbstractCassandraConfiguration {
private static final String KEYSPACE = "example";
#Override
public String getKeyspaceName() {
return KEYSPACE;
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE_DROP_UNUSED;
}
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
List<CreateKeyspaceSpecification> createKeyspaceSpecifications = new ArrayList<>();
createKeyspaceSpecifications.add(getKeySpaceSpecification());
return createKeyspaceSpecifications;
}
// Below method creates KEYSPACE if it doesnt exist.
private CreateKeyspaceSpecification getKeySpaceSpecification() {
CreateKeyspaceSpecification pandaCoopKeyspace = new CreateKeyspaceSpecification();
pandaCoopKeyspace.name(KEYSPACE);
pandaCoopKeyspace.ifNotExists(true)
.createKeyspace();
return pandaCoopKeyspace;
}
#Override
public String getContactPoints() {
return "localhost";
}
#Override
public String[] getEntityBasePackages() {
return new String[] {"unicon.matthews.oneroster.service.repository"};
}
}
}
This is the Entity pojo class:
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.Indexed;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import com.datastax.driver.core.DataType;
import unicon.matthews.entity.DataSync;
import unicon.matthews.oneroster.Org;
import unicon.matthews.oneroster.OrgType;
import unicon.matthews.oneroster.Status;
#Table(value=OrgCassandraTable.tableName)
public class OrgCassandraTable implements Serializable{
#org.springframework.data.annotation.Transient
public static final String tableName = "org";
#PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
#CassandraType(type = DataType.Name.TEXT)
#Column("id")
private String id;
#Indexed
#CassandraType(type = DataType.Name.TEXT)
#Column("tenant_id")
private String tenantId;
#Indexed
#CassandraType(type = DataType.Name.TEXT)
#Column("api_key")
private String apiKey;
#Indexed
#CassandraType(type = DataType.Name.TEXT)
#Column("api_secret")
private String apiSecret;
#Indexed
#CassandraType(type = DataType.Name.TEXT)
#Column("org_source_id")
private String sourcedId;
#CassandraType(type = DataType.Name.TEXT)
#Column("org_status")
private String status;
#Column("org_metadata")
private Map<String, String> metadata;
#Column("org_dateLastModified")
#LastModifiedDate
private LocalDateTime dateLastModified;
#Column("org_name")
#CassandraType(type = DataType.Name.TEXT)
private String name;
// ojito que esto es un enum
#Column("org_type")
#CassandraType(type = DataType.Name.TEXT)
private String type;
#Column("org_identifier")
#CassandraType(type = DataType.Name.TEXT)
#Indexed
private String identifier;
// THIS FIELD LOOKS TO BE THE PROBLEM!
#Column("org_data_syncs")
#CassandraType(type = DataType.Name.TEXT)
private Set<DataSync> dataSyncs;
public OrgCassandraTable(){
}
This is DataSync class. It belongs to a third party library, i do not have the code. What do am i doing wrong?
public class DataSync implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String orgId;
private String tenantId;
private LocalDateTime syncDateTime;
private DataSync.DataSyncType syncType;
private DataSync.DataSyncStatus syncStatus;
...getters, setters, equals, hashCode, toString methods
}
...
// getters, setters, hashCode, equals, toString methods.
}
Cassandra is a column-oriented store – Spring Data Cassandra maps each domain class to a single table, there are no relations, and there is no (not yet, but might come) support for embedded objects. Embedded objects in the sense of flattening the data structure to the columns of the table the enclosing object maps to.
However, there is support for user-defined types via #UserDefinedType on the object class representing the data structure. Adding #UserDefinedType requires having control over the class/code.
If you want to stick to the class, then you still have an option to serialize the data yourself, e.g., using Jackson and storing the JSON inside a single Cassandra column:
static class DataSyncWriteConverter implements Converter<DataSync, String> {
public String convert(DataSync source) {
try {
return new ObjectMapper().writeValueAsString(source);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
You should be able to work with collection types as well, meaning, that you can persist a Set<DataSync> within a set<varchar> column in Cassandra with this approach.
One last thing: Using 3rd-party classes comes at the risk of changes to the external classes where you don't have control over. Creating an own data structure by replicating all fields and mapping the data to the 3rd-party-class give you control over the lifecycle of changes.
References:
Saving using a registered Spring Converter.

Categories

Resources