Asserion failed service testing spring - spring

I have a simple shampoos-warehouse api and want to test it service logic, but something going wrong.
Here's my Service Test:
RunWith(SpringRunner.class)
#SpringBootTest
class ShampooServiceTest {
public static final String SHAMPOO_NAME = "name";
public static final int SHAMPOO_CAPACITY = 1000;
public static final int SHAMPOO_QUANTITY = 30;
public static final boolean SHAMPOO_IS_HEALTHY = true;
public static final LocalDate SHAMPOO_EXPIRATION_DATE = LocalDate.parse("2022-11-11");
public static final String SHAMPOO_PARAM = "equals";
#Autowired
ShampooService shampooService;
#MockBean
ShampooRepository shampooRepository;
#Test
void getAddAndGetTotalShampoosByParams(){
shampooService.addShampoos(UUID.randomUUID(), SHAMPOO_NAME, SHAMPOO_CAPACITY, SHAMPOO_QUANTITY, SHAMPOO_IS_HEALTHY, SHAMPOO_EXPIRATION_DATE);
assertEquals(String.valueOf(SHAMPOO_QUANTITY), shampooService.getTotalShampoosByParam(SHAMPOO_NAME, SHAMPOO_CAPACITY, SHAMPOO_PARAM));
}
I have an assertion error here:
org.opentest4j.AssertionFailedError:
Expected :30
Actual :0
Here's my DTO:
public class ShampooDto {
public interface IncomeValidation{}
public interface OutcomeValidation{}
#NotNull(groups={IncomeValidation.class, OutcomeValidation.class})
private String name;
#Min(100)
#Max(5000)
#NotNull(groups={IncomeValidation.class, OutcomeValidation.class})
private int capacity;
#NotNull(groups={IncomeValidation.class, OutcomeValidation.class})
private int quantity;
#NotNull(groups={IncomeValidation.class})
private boolean healthy;
#NotNull(groups={IncomeValidation.class})
private LocalDate expiration_date;
}
And here's my service:
public String getTotalShampoosByParam(String name, int capacity, String param){
Integer totalQuantity;
switch (param){
case "less":
totalQuantity = shampooRepository.getTotalQuantityWhereCapacityLess(name, capacity);
break;
case "equals":
totalQuantity = shampooRepository.getTotalQuantityWhereCapacityEquals(name, capacity);
break;
case "more":
totalQuantity = shampooRepository.getTotalQuantityWhereCapacityMore(name, capacity);
break;
default:
totalQuantity = 0;
}
if(totalQuantity!=null){
return String.valueOf(totalQuantity);
}
else{
return "0";
}
}
public Shampoo addShampoos(UUID id, String name, int capacity, int quantity, boolean healthy, LocalDate expiration_date) throws ValidationException {
Optional<Shampoo> answer = shampooRepository.findShampooByNameAndCapacity(name, capacity);
if(answer.isPresent()){
Shampoo shampoo = answer.get();
shampoo.setQuantity(shampoo.getQuantity() + quantity);
shampooRepository.save(shampoo);
return shampoo;
}
else{
Shampoo shampoo = new Shampoo(id, name, capacity, quantity, healthy, expiration_date, LocalDate.now());
shampooRepository.save(shampoo);
return shampoo;
}
}
The problem is that when I added Shampoos and search it by requests, all works, but my test give me "0" instead of "30"

Related

Optional int parameter 'movieId' is present but cannot be translated into a null value

I am working on Maven multi module project so this might build error?
I am trying to perform unit test of delete method from controller and I quite don't understand why it is happening here because methods similar to this one works.
Exception speaks for itself - cannot convert int to null. But why there is null value where it looks like curl looks correct?
{"timestamp":"2019-12-16T11:47:35.450+0000","path":"/movie-composite/1","status":500,"error":"Internal Server Error","message":"Optional int parameter 'movieId' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type."}
Ho mapping looks like:
/**
* Sample usage: curl $HOST:$PORT/movie-composite/1
*
* #param movieId
*/
#ApiOperation(
value = "${api.movie-composite.delete-composite-movie.description}",
notes = "${api.movie-composite.delete-composite-movie.notes}")
#ApiResponses(value = {
#ApiResponse(code = 400, message = "Bad Request, invalid format of the request. See response message for more information."),
#ApiResponse(code = 422, message = "Unprocessable entity, input parameters caused the processing to fails. See response message for more information.")
})
#DeleteMapping(
value = "/movie-composite/{movieId}",
produces = "application/json")
void deleteCompositeMovie(#PathVariable int movieId);
its implementation:
#Override
public void deleteCompositeMovie(int movieId) {
log.debug("deleteCompositeMovie will delete Movie, Reviews, Recommendations belonging to Movie with id: {}", movieId);
movieCompositeIntegration.deleteMovie(movieId);
movieCompositeIntegration.deleteReviews(movieId);
movieCompositeIntegration.deleteRecommendations(movieId);
log.debug("deleteCompositeMovie deleted Movie, Reviews, Recommendations belonging to Movie with id: {}", movieId);
}
And finally test that won't pass:
#Test
void deleteCompositeMovie() {
int given = 1;
deleteAndVerify(given, HttpStatus.OK);
verify(baseMovieCompositeService, times(1)).deleteCompositeMovie(given);
}
where deleteAndVerify(given, HttpStatus.OK) looks like:
private void deleteAndVerify(int id, HttpStatus httpStatus) {
webTestClient.delete()
.uri("/movie-composite/" + id)
.exchange()
.expectStatus().isEqualTo(httpStatus);
}
complete test file looks like:
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = RANDOM_PORT)
public class MovieCompositeServiceApplicationTests {
public static final String FAKE_ADDRESS = "Fake address";
public static final String FAKE_GENRE = "Fake genre";
public static final String FAKE_TITLE = "Fake title";
#Autowired
WebTestClient webTestClient;
#MockBean
MovieCompositeIntegration movieCompositeIntegration;
#MockBean
BaseMovieCompositeService baseMovieCompositeService;
#MockBean
ServiceUtil serviceUtil;
#Test
void createMovie() {
int movieId = 1;
MovieAggregate movieAggregate = MovieAggregate.builder()
.movieId(movieId)
.genre(FAKE_GENRE)
.title(FAKE_TITLE)
.recommendations(getRecommendationSummaries())
.reviews(getReviewSummaries())
.serviceAddresses(null)
.build();
postAndVerify(movieAggregate);
}
#Test
void getMovieById() {
int given = 1;
Movie movie = getMovies(given);
Mockito.when(serviceUtil.getServiceAddress()).thenReturn("Fake service address");
List<Recommendation> recommendations = getRecommendations(movie);
List<Review> reviews = getReviews(movie);
Mockito.when(movieCompositeIntegration.getMovie(given)).thenReturn(movie);
Mockito.when(movieCompositeIntegration.getRecommendations(movie.getMovieId())).thenReturn(recommendations);
Mockito.when(movieCompositeIntegration.getReviews(movie.getMovieId())).thenReturn(reviews);
getAndVerifyMovie(given, HttpStatus.OK)
.jsonPath("$.movieId").isEqualTo(given)
.jsonPath("$.recommendations.length()").isEqualTo(3)
.jsonPath("$.reviews.length()").isEqualTo(3);
}
#Test
void getMovieByIdThrowsNotFoundException() {
int given = 1;
Mockito.when(movieCompositeIntegration.getMovie(given)).thenThrow(NotFoundException.class);
getAndVerifyMovie(given, HttpStatus.NOT_FOUND)
.jsonPath("$.path").isEqualTo("/movie-composite/" + given);
}
#Test
void getMovieByIdThrowsInvalidInputException() {
int given = 1;
Mockito.when(movieCompositeIntegration.getMovie(given)).thenThrow(InvalidInputException.class);
getAndVerifyMovie(given, HttpStatus.UNPROCESSABLE_ENTITY)
.jsonPath("$.path").isEqualTo("/movie-composite/" + given);
}
#Test
void deleteCompositeMovie() {
int given = 1;
deleteAndVerify(given, HttpStatus.OK);
verify(baseMovieCompositeService, times(1)).deleteCompositeMovie(given);
}
private WebTestClient.BodyContentSpec getAndVerifyMovie(int id, HttpStatus status) {
return webTestClient.get()
.uri("/movie-composite/" + id)
.accept(MediaType.APPLICATION_JSON_UTF8)
.exchange()
.expectStatus().isEqualTo(status)
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
.expectBody();
}
private WebTestClient.BodyContentSpec postAndVerify(MovieAggregate movieAggregate) {
return webTestClient.post()
.uri("/movie-composite")
.body(just(movieAggregate), MovieAggregate.class)
.exchange()
.expectStatus().isEqualTo(HttpStatus.OK)
.expectBody();
}
private void deleteAndVerify(int id, HttpStatus httpStatus) {
webTestClient.delete()
.uri("/movie-composite/" + id)
.exchange()
.expectStatus().isEqualTo(httpStatus);
}
private List<ReviewSummary> getReviewSummaries() {
return Collections.singletonList(ReviewSummary.builder().reviewId(1).subject("s").author("a").content("c").build());
}
private List<RecommendationSummary> getRecommendationSummaries() {
return Collections.singletonList(RecommendationSummary.builder().recommendationId(1).author("a").content("c").rate(1).build());
}
private Movie getMovies(int given) {
return Movie.builder().movieId(given).address(FAKE_ADDRESS).genre(FAKE_GENRE).title(FAKE_TITLE).build();
}
private List<Review> getReviews(Movie movie) {
return Arrays.asList(
Review.builder().movieId(movie.getMovieId()).reviewId(1).author("Author 1").subject("Subject 1").content("Content 1").serviceAddress(serviceUtil.getServiceAddress()).build(),
Review.builder().movieId(movie.getMovieId()).reviewId(2).author("Author 2").subject("Subject 2").content("Content 2").serviceAddress(serviceUtil.getServiceAddress()).build(),
Review.builder().movieId(movie.getMovieId()).reviewId(3).author("Author 2").subject("Subject 3").content("Content 3").serviceAddress(serviceUtil.getServiceAddress()).build()
);
}
private List<Recommendation> getRecommendations(Movie movie) {
return Arrays.asList(
Recommendation.builder().movieId(movie.getMovieId()).recommendationId(1).author("Author 1").rate(1).content("Content 1").serviceAddress(serviceUtil.getServiceAddress()).build(),
Recommendation.builder().movieId(movie.getMovieId()).recommendationId(2).author("Author 2").rate(2).content("Content 2").serviceAddress(serviceUtil.getServiceAddress()).build(),
Recommendation.builder().movieId(movie.getMovieId()).recommendationId(3).author("Author 3").rate(3).content("Content 3").serviceAddress(serviceUtil.getServiceAddress()).build()
);
}
}
Why it won't pass where getMovieById() looks very similar when it comes to input and url and it passes?

Performance problem when query a many-to-one relation by jpa

I use spring-boot-data-jpa-2.0 to get data from db. A table has many-to-one relation, and the query speed is too slow, 1000 lines data with foreign key will cost 15s, but by native sql it will cost only 0.07s. I search the issue and found that it is because 1+n problem.
Some solution that says use 'join fetch' in hql can solve. When I use the 'join fetch' in hql, query speed not change.
The system designed as a pure rest service, with spring boot framework.
contract entity
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "MA_CONTRACTINFO_B")
public class MaContractinfoB implements java.io.Serializable {
// Fields
private String contractcd;
private MaDepartmentB maDepartmentB;
private Double contractid;
private String contractnm;
private String partya;
private String deputycontract;
private String prjtype;
private Double fundt;
private String bustype;
private String contractstatus;
private Double contractyear;
private String fundratio;
private LocalDateTime signdate;
private String prj;
private LocalDateTime loaddate;
private String udep;
private Double fundaccont;
private Double receipt;
private Double fundacctot;
private Double receiptot;
private String loc;
private String riskasscd;
private String rm;
private String pm;
private Double fundaccrec;
private String adminleader;
private String techleader;
private String leader;
private String progress;
private String cashadmin;
private String timetask;
private String contracttp;
// Constructors
/** default constructor */
public MaContractinfoB() {
}
/** minimal constructor */
public MaContractinfoB(String contractcd) {
this.contractcd = contractcd;
}
/** full constructor */
public MaContractinfoB(String contractcd, MaDepartmentB maDepartmentB, Double contractid, String contractnm,
String partya, String deputycontract, String prjtype, Double fundt, String bustype, String contractstatus,
Double contractyear, String fundratio, LocalDateTime signdate, String prj, LocalDateTime loaddate,
String udep, Double fundaccont, Double receipt, Double fundacctot, Double receiptot, String loc,
String riskasscd, String rm, String pm, Double fundaccrec, String adminleader, String techleader,
String leader, String progress, String cashadmin, String timetask, String contracttp) {
this.contractcd = contractcd;
this.maDepartmentB = maDepartmentB;
this.contractid = contractid;
this.contractnm = contractnm;
this.partya = partya;
this.deputycontract = deputycontract;
this.prjtype = prjtype;
this.fundt = fundt;
this.bustype = bustype;
this.contractstatus = contractstatus;
this.contractyear = contractyear;
this.fundratio = fundratio;
this.signdate = signdate;
this.prj = prj;
this.loaddate = loaddate;
this.udep = udep;
this.fundaccont = fundaccont;
this.receipt = receipt;
this.fundacctot = fundacctot;
this.receiptot = receiptot;
this.loc = loc;
this.riskasscd = riskasscd;
this.rm = rm;
this.pm = pm;
this.fundaccrec = fundaccrec;
this.adminleader = adminleader;
this.techleader = techleader;
this.leader = leader;
this.progress = progress;
this.cashadmin = cashadmin;
this.timetask = timetask;
this.contracttp = contracttp;
}
// Property accessors
#Id
#Column(name = "CONTRACTCD", unique = true, nullable = false)
public String getContractcd() {
return this.contractcd;
}
public void setContractcd(String contractcd) {
this.contractcd = contractcd;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "DEPID")
public MaDepartmentB getMaDepartmentB() {
return this.maDepartmentB;
}
public void setMaDepartmentB(MaDepartmentB maDepartmentB) {
this.maDepartmentB = maDepartmentB;
}
#Column(name = "CONTRACTID", precision = 38, scale = 8)
public Double getContractid() {
return this.contractid;
}
public void setContractid(Double contractid) {
this.contractid = contractid;
}
#Column(name = "CONTRACTNM")
public String getContractnm() {
return this.contractnm;
}
public void setContractnm(String contractnm) {
this.contractnm = contractnm;
}
#Column(name = "PARTYA")
public String getPartya() {
return this.partya;
}
public void setPartya(String partya) {
this.partya = partya;
}
#Column(name = "DEPUTYCONTRACT")
public String getDeputycontract() {
return this.deputycontract;
}
public void setDeputycontract(String deputycontract) {
this.deputycontract = deputycontract;
}
#Column(name = "PRJTYPE")
public String getPrjtype() {
return this.prjtype;
}
public void setPrjtype(String prjtype) {
this.prjtype = prjtype;
}
#Column(name = "FUNDT", precision = 38, scale = 8)
public Double getFundt() {
return this.fundt;
}
public void setFundt(Double fundt) {
this.fundt = fundt;
}
#Column(name = "BUSTYPE")
public String getBustype() {
return this.bustype;
}
public void setBustype(String bustype) {
this.bustype = bustype;
}
#Column(name = "CONTRACTSTATUS")
public String getContractstatus() {
return this.contractstatus;
}
public void setContractstatus(String contractstatus) {
this.contractstatus = contractstatus;
}
#Column(name = "CONTRACTYEAR", precision = 38, scale = 8)
public Double getContractyear() {
return this.contractyear;
}
public void setContractyear(Double contractyear) {
this.contractyear = contractyear;
}
#Column(name = "FUNDRATIO")
public String getFundratio() {
return this.fundratio;
}
public void setFundratio(String fundratio) {
this.fundratio = fundratio;
}
#Column(name = "SIGNDATE", length = 11)
public LocalDateTime getSigndate() {
return this.signdate;
}
public void setSigndate(LocalDateTime signdate) {
this.signdate = signdate;
}
#Column(name = "PRJ")
public String getPrj() {
return this.prj;
}
public void setPrj(String prj) {
this.prj = prj;
}
#Column(name = "LOADDATE", length = 11)
public LocalDateTime getLoaddate() {
return this.loaddate;
}
public void setLoaddate(LocalDateTime loaddate) {
this.loaddate = loaddate;
}
#Column(name = "UDEP")
public String getUdep() {
return this.udep;
}
public void setUdep(String udep) {
this.udep = udep;
}
#Column(name = "FUNDACCONT", precision = 38, scale = 8)
public Double getFundaccont() {
return this.fundaccont;
}
public void setFundaccont(Double fundaccont) {
this.fundaccont = fundaccont;
}
#Column(name = "RECEIPT", precision = 38, scale = 8)
public Double getReceipt() {
return this.receipt;
}
public void setReceipt(Double receipt) {
this.receipt = receipt;
}
#Column(name = "FUNDACCTOT", precision = 38, scale = 8)
public Double getFundacctot() {
return this.fundacctot;
}
public void setFundacctot(Double fundacctot) {
this.fundacctot = fundacctot;
}
#Column(name = "RECEIPTOT", precision = 38, scale = 8)
public Double getReceiptot() {
return this.receiptot;
}
public void setReceiptot(Double receiptot) {
this.receiptot = receiptot;
}
#Column(name = "LOC")
public String getLoc() {
return this.loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
#Column(name = "RISKASSCD")
public String getRiskasscd() {
return this.riskasscd;
}
public void setRiskasscd(String riskasscd) {
this.riskasscd = riskasscd;
}
#Column(name = "RM")
public String getRm() {
return this.rm;
}
public void setRm(String rm) {
this.rm = rm;
}
#Column(name = "PM")
public String getPm() {
return this.pm;
}
public void setPm(String pm) {
this.pm = pm;
}
#Column(name = "FUNDACCREC", precision = 38, scale = 8)
public Double getFundaccrec() {
return this.fundaccrec;
}
public void setFundaccrec(Double fundaccrec) {
this.fundaccrec = fundaccrec;
}
#Column(name = "ADMINLEADER")
public String getAdminleader() {
return this.adminleader;
}
public void setAdminleader(String adminleader) {
this.adminleader = adminleader;
}
#Column(name = "TECHLEADER")
public String getTechleader() {
return this.techleader;
}
public void setTechleader(String techleader) {
this.techleader = techleader;
}
#Column(name = "LEADER", length = 20)
public String getLeader() {
return this.leader;
}
public void setLeader(String leader) {
this.leader = leader;
}
#Column(name = "PROGRESS", length = 1000)
public String getProgress() {
return this.progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
#Column(name = "CASHADMIN", length = 20)
public String getCashadmin() {
return this.cashadmin;
}
public void setCashadmin(String cashadmin) {
this.cashadmin = cashadmin;
}
#Column(name = "TIMETASK", length = 2000)
public String getTimetask() {
return this.timetask;
}
public void setTimetask(String timetask) {
this.timetask = timetask;
}
#Column(name = "CONTRACTTP", length = 50)
public String getContracttp() {
return this.contracttp;
}
public void setContracttp(String contracttp) {
this.contracttp = contracttp;
}
/**
* toString
*
* #return String
*/
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName()).append("#").append(Integer.toHexString(hashCode())).append(" [");
buffer.append("contractcd").append("='").append(getContractcd()).append("' ");
buffer.append("maDepartmentB").append("='").append(getMaDepartmentB()).append("' ");
buffer.append("contractid").append("='").append(getContractid()).append("' ");
buffer.append("contractnm").append("='").append(getContractnm()).append("' ");
buffer.append("partya").append("='").append(getPartya()).append("' ");
buffer.append("deputycontract").append("='").append(getDeputycontract()).append("' ");
buffer.append("prjtype").append("='").append(getPrjtype()).append("' ");
buffer.append("fundt").append("='").append(getFundt()).append("' ");
buffer.append("bustype").append("='").append(getBustype()).append("' ");
buffer.append("contractstatus").append("='").append(getContractstatus()).append("' ");
buffer.append("contractyear").append("='").append(getContractyear()).append("' ");
buffer.append("fundratio").append("='").append(getFundratio()).append("' ");
buffer.append("signdate").append("='").append(getSigndate()).append("' ");
buffer.append("prj").append("='").append(getPrj()).append("' ");
buffer.append("loaddate").append("='").append(getLoaddate()).append("' ");
buffer.append("udep").append("='").append(getUdep()).append("' ");
buffer.append("fundaccont").append("='").append(getFundaccont()).append("' ");
buffer.append("receipt").append("='").append(getReceipt()).append("' ");
buffer.append("fundacctot").append("='").append(getFundacctot()).append("' ");
buffer.append("receiptot").append("='").append(getReceiptot()).append("' ");
buffer.append("loc").append("='").append(getLoc()).append("' ");
buffer.append("riskasscd").append("='").append(getRiskasscd()).append("' ");
buffer.append("rm").append("='").append(getRm()).append("' ");
buffer.append("pm").append("='").append(getPm()).append("' ");
buffer.append("fundaccrec").append("='").append(getFundaccrec()).append("' ");
buffer.append("adminleader").append("='").append(getAdminleader()).append("' ");
buffer.append("techleader").append("='").append(getTechleader()).append("' ");
buffer.append("leader").append("='").append(getLeader()).append("' ");
buffer.append("progress").append("='").append(getProgress()).append("' ");
buffer.append("cashadmin").append("='").append(getCashadmin()).append("' ");
buffer.append("timetask").append("='").append(getTimetask()).append("' ");
buffer.append("contracttp").append("='").append(getContracttp()).append("' ");
buffer.append("]");
return buffer.toString();
}
}
department entity
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.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "MA_DEPARTMENT_B")
public class MaDepartmentB implements java.io.Serializable {
// Fields
private Long id;
private String name;
private String leader;
private Set<MaContractinfoB> maContractinfoBs = new HashSet<MaContractinfoB>(0);
private Set<MaContraimB> maContraimBs = new HashSet<MaContraimB>(0);
// Constructors
/** default constructor */
public MaDepartmentB() {
}
/** minimal constructor */
public MaDepartmentB(Long id) {
this.id = id;
}
/** full constructor */
public MaDepartmentB(Long id, String name, String leader, Set<MaContractinfoB> maContractinfoBs,
Set<MaContraimB> maContraimBs) {
this.id = id;
this.name = name;
this.leader = leader;
this.maContractinfoBs = maContractinfoBs;
this.maContraimBs = maContraimBs;
}
// Property accessors
#Id
#Column(name = "ID", unique = true, nullable = false, precision = 10, scale = 0)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "NAME")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "LEADER")
public String getLeader() {
return this.leader;
}
public void setLeader(String leader) {
this.leader = leader;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "maDepartmentB")
public Set<MaContractinfoB> getMaContractinfoBs() {
return this.maContractinfoBs;
}
public void setMaContractinfoBs(Set<MaContractinfoB> maContractinfoBs) {
this.maContractinfoBs = maContractinfoBs;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "maDepartmentB")
public Set<MaContraimB> getMaContraimBs() {
return this.maContraimBs;
}
public void setMaContraimBs(Set<MaContraimB> maContraimBs) {
this.maContraimBs = maContraimBs;
}
/**
* toString
*
* #return String
*/
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(getClass().getName()).append("#").append(Integer.toHexString(hashCode())).append(" [");
buffer.append("id").append("='").append(getId()).append("' ");
buffer.append("name").append("='").append(getName()).append("' ");
buffer.append("leader").append("='").append(getLeader()).append("' ");
buffer.append("maContractinfoBs").append("='").append(getMaContractinfoBs()).append("' ");
buffer.append("maContraimBs").append("='").append(getMaContraimBs()).append("' ");
buffer.append("]");
return buffer.toString();
}
}
jparepository
public interface MaContractinfoBRepository extends JpaRepository<MaContractinfoB, Long> {
#Query("from MaContractinfoB c join fetch c.maDepartmentB")
List<MaContractinfoB> findAll();
#Query("select contractnm from MaContractinfoB")
List<String> findAllName();
// #Query("from MaContractinfoB c join fetch c.maDepartmentB")
// List test();
}
In MaContractinfoBRepository, When I use findAllName function, it will immediately return 1000 contract names in 0.05s. When I use findAll, it will cost 15s to get 1000 data with department entity, even I add join fetch. But if I get it by native sql in db tool such as navicat, it will cost only 0.07s.
Is any keypoint I missed? How to query the MaContractinfoB table not so slowly?
This is happening because internally with 'fetch' command also hibernate is lazy loading all the rows of Department entity for each Contract id whenever you call the findAll() method. So if there are n rows in Department for 1 Contract and in total there are m Contracts then the total number of calls to the database would be 'm * n'.
One way around this is by using DTO projections. Data Transfer Objects is an easy way to define all the required columns in one query and hit the database for once.
I have found this article useful which shows multiple ways of writing DTO projections.
https://thoughts-on-java.org/dto-projections/
One of the mentioned way is: Using JPQL you can use a constructor expression to define a constructor call with the keyword new followed by the fully classified class name of your DTO and a list of constructor parameters in curly braces.
Something like this:
TypedQuery<ContractWithDepartmentDetails> q = em.createQuery(
"SELECT new com.practice.model.ContractWithDepartmentDetails(c.id, c.name, d.name) FROM contract c JOIN c.department d",
ContractWithDepartmentDetails.class);

JPA - Get values from fields in other entities in a Controller class

I have two entities: Room and Service. I also have a method in Logic class that i want to use in ServiceController class. Other classes are irrelevant.
room.getBeds() always returns 0, default int value.
Room entity:
#Entity
public class Room {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int room_id;
private int beds;
private int number;
public Room() {
}
public Room(int beds, int number) {
this.beds = beds;
this.number = number;
}
public int getRoom_id() {
return room_id;
}
public void setRoom_id(int room_id) {
this.room_id = room_id;
}
public int getBeds() {
return beds;
}
public void setBeds(int beds) {
this.beds = beds;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Service entity:
#Entity
public class Service {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int service_id;
#JsonFormat(pattern = "dd/MM/yyyy", timezone = "Europe/Berlin")
private Date arrival_at;
#JsonFormat(pattern = "dd/MM/yyyy", timezone = "Europe/Berlin")
private Date departure_at;
private int meals;
private int guest_id;
private double price;
public int getService_id() {
return service_id;
}
public void setService_id(int service_id) {
this.service_id = service_id;
}
public Date getArrival_at() {
return arrival_at;
}
public void setArrival_at(Date arrival_at) {
this.arrival_at = arrival_at;
}
public Date getDeparture_at() {
return departure_at;
}
public void setDeparture_at(Date departure_at) {
this.departure_at = departure_at;
}
public int getMeals() {
return meals;
}
public void setMeals(int meals) {
this.meals = meals;
}
public int getGuest_id() {
return guest_id;
}
public void setGuest_id(int guest_id) {
this.guest_id = guest_id;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
Service controller:
#RestController
public class ServiceController {
#Autowired
ServiceRepository serviceRepository;
private Logic logic = new Logic();
private Room room = new Room();
//CREATE
#PostMapping("/services")
public int createService(#RequestBody Service service) {
service.setPrice(logic.calculatePrice(service.getArrival_at(), service.getDeparture_at(), room.getBeds(), service.getMeals()));
return serviceRepository.save(service);
}
}
How to get the correct value from room.getBeds() getter?
Lerius you are just making a new object of Room Entity and are not populating any values from your Database to that object
that is the reason why it is taking room.getBeds(); as 0(i.e default value for int)
Try Populating DB values to your object after that you will be able to get the value of getBeds();

Comparing dates in ascending and descending order in arrayList not working

I have an array of email objects. I need to sort them by two fields. the first field is by subject, which i have working, and the other is by date which I cannot get. I tried a bunch of other people's solutions but nothing seems to work. Here is an excerpt of my code:
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Comparator;
import java.util.Date;
public class Email implements Comparable{
private String to;
private String cc;
private String bcc;
private String subject;
private String body;
private GregorianCalendar timestamp; //time that email was created
//constructors and getters and setters (besides timeStamp) omitted to save space
public Date getTimestamp() {
return timestamp.getTime();
}
public void setTimestamp(GregorianCalendar timestamp) {
this.timestamp = timestamp;
}
//This works
public static Comparator<Email> emailSubjectComparatorAscending = new Comparator<Email>(){
public int compare(Email e1, Email e2) {
String EmailSubject1 = e1.getSubject().toLowerCase();
String EmailSubject2 = e2.getSubject().toLowerCase();
return EmailSubject1.compareTo(EmailSubject2);
}
};
//This works
public static Comparator<Email> emailSubjectComparatorDescending = new Comparator<Email>(){
public int compare(Email e1, Email e2) {
String EmailSubject1 = e1.getSubject().toLowerCase();
String EmailSubject2 = e2.getSubject().toLowerCase();
return EmailSubject2.compareTo(EmailSubject1);
}
};
//This doesn't work
public static Comparator<Email> emailDateComparatorAscending = new Comparator<Email>(){
#Override
public int compare(Email o1, Email o2) {
if(o1.getTimestamp().equals(o2.getTimestamp()))
return 0;
if(o2.getTimestamp().before(o1.getTimestamp()))
return 1;
else
return -1;
}
};
//This doesn't work
public static Comparator<Email> emailDateComparatorDescending = new Comparator<Email>(){
#Override
public int compare(Email o1, Email o2) {
if(o1.getTimestamp().equals(o2.getTimestamp()))
return 0;
if(o1.getTimestamp().before(o2.getTimestamp()))
return 1;
else
return -1;
}
};
#Override
public String toString(){
return("To: " + to + "\nCC: " + cc + "\nBCC: " + bcc + "\nSubject: " + subject + "\n" + body);
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
here is the part of my other class, in which I call these sorting methods:
import java.util.*;
public class Folder{
private ArrayList<Email> emails; //initialize?
private String name;
private String currentSortingMethod; //default = descending
public Folder(String name) {
super();
this.name = name;
currentSortingMethod = "sortByDateDescending";
emails = new ArrayList<Email>(); //instantiate the arrayList
}
//omitted getters, setters and other irrelevant methods
//This works
public void sortBySubjectAscending(){
Collections.sort(emails, Email.emailSubjectComparatorAscending);
currentSortingMethod = "sortBySubjectAscending";
}
//This works
public void sortBySubjectDescending(){
Collections.sort(emails, Email.emailSubjectComparatorDescending);
currentSortingMethod = "sortBySubjectDescending";
}
//This doesn't work
public void sortByDateAscending(){
Collections.sort(emails, Email.emailDateComparatorAscending);
currentSortingMethod = "sortByDateAscending";
}
//This doesn't work
public void sortByDateDescending(){
Collections.sort(emails, Email.emailDateComparatorDescending);
currentSortingMethod = "sortByDateDescending";
}
I am really confused with this and I have tried so many different ways and none work. If anyone could explain how to make this work I would appreciate it greatly

Spring merge - java.sql.SQLException: Invalid column index

I have a table that has 2 columns that create the primary key:
#Entity
#Table(name="DW.DW$SF$MONTHLY")
public class DWMonthly implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId DWMonthlyPK monthlyPK;
#Id
#Column(name="AID", insertable=false, updatable=false)
#IndexColumn(name="DW$SF$MONTHLY_PK")
private Long id;
#Column(name="CHNG_STATUS")
private BigDecimal chngStatus;
#Column(name="NAR")
private BigDecimal nar;
#Column(name="SF_AMID")
private String sfAmid;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="N_DATE", insertable=false, updatable=false)
#IndexColumn(name="DW$SF$MONTHLY_PK")
private Date nDate;
public DWMonthly() {}
public DWMonthly(Long id, String sfAmid, Date nDate) {
this.id = id;
this.sfAmid = sfAmid;
this.nDate = nDate;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getChngStatus() {
return this.chngStatus;
}
public void setChngStatus(BigDecimal chngStatus) {
this.chngStatus = chngStatus;
}
public BigDecimal getNar() {
return this.nar;
}
public void setNar(BigDecimal nar) {
this.nar = nar;
}
public String getSfAmid() {
return this.sfAmid;
}
public void setSfAmid(String sfAmid) {
this.sfAmid = sfAmid;
}
public Date getNDate() {
return nDate;
}
public void setNarDate(Date nDate) {
this.nDate = nDate;
}
}
Embeddable table:
#Embeddable
public class DWMonthlyPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="AID")
private long aid;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="N_DATE")
private java.util.Date nDate;
public DWMonthlyPK() {
}
public long getAid() {
return this.aid;
}
public void setAid(long aid) {
this.aid = aid;
}
public java.util.Date getNDate() {
return this.narDate;
}
public void setNDate(java.util.Date nDate) {
this.nDate = nDate;
}
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof DWMonthlyPK)) {
return false;
}
DWMonthlyPK castOther = (DWMonthlyPK)other;
return
(this.aid == castOther.aid)
&& this.nDate.equals(castOther.nDate);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + ((int) (this.aid ^ (this.aid >>> 32)));
hash = hash * prime + this.nDate.hashCode();
return hash;
}
}
Find the record and update:
#Repository(value="MonthlyNarDaoRepository")
#Import({JpaConfigurationImpl.class})
#Transactional(value="dwTransactionManager",readOnly = true, propagation=Propagation.REQUIRES_NEW)
public class MonthlyNarDaoImpl implements MonthlyNarDao {
#Override
#Transactional(value="dwTransactionManager")
public void findAndUpdateMonhtlyByAccountId(Map<DWAccount, UpsertResult> accountsLoadedResult) {
for (DWAccount dwAccount : accountsLoadedResult.keySet()){
try {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<DWMonthlyNar> criteriaQuery = criteriaBuilder.createQuery(DWMonthlyNar.class);
Root<DWMonthlyNar> root = criteriaQuery.from(DWMonthlyNar.class);
Predicate p = criteriaBuilder.conjunction();
p = criteriaBuilder.and(criteriaBuilder.equal(root.get("id"), dwAccount.getId()), criteriaBuilder.notEqual(root.get("nar").as(BigDecimal.class), new BigDecimal(0.0)), criteriaBuilder.isNull(root.get("sfAmid")));
criteriaQuery.select(root);
criteriaQuery.where(p);
for (DWMonthlyNar dwMonthlyNar : this.entityManager.createQuery(criteriaQuery).getResultList()){
if (dwMonthlyNar.getSfAmid()==null || !dwMonthlyNar.getSfAmid().equals(accountsLoadedResult.get(dwAccount).getId())){
dwMonthlyNar.setSfAmid(accountsLoadedResult.get(dwAccount).getId());
this.entityManager.merge(dwMonthlyNar);
}
}
} catch (Exception e) {
logger.error("MonthlyNarDaoImpl.findAndUpdateMonhtlyNarByAccountId(): " + e.getMessage());
}
}
}
}
Error:
Hibernate: update DW.DW$SF$MONTHLY set CHNG_STATUS=?, NAR=?,
SF_AMID=? where AID=? and NAR_DATE=? 16:04:58.864 [main] DEBUG
o.h.e.jdbc.spi.SqlExceptionHelper - Invalid column index [n/a]
java.sql.SQLException: Invalid column index

Resources