java.util.NoSuchElementException: No value present - java

So my problem is in a Test, when I call the method to test it gives this error:
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:143)
at com.MD.Medicine.Services.SaveService.savePlans(SaveService.java:57)
at com.MD.Medicine.Services.SaveServiceTest.testSavePlans_failPills(SaveServiceTest.java:99)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
My test:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SaveServiceTest {
#MockBean
private MedsRepo medsRepo;
#MockBean
private PlansRepo plansRepo;
#MockBean
private PlanDayRepo planDayRepo;
#Autowired
private SaveService saveService;
#Test
void testSavePlans_failPills() {
LocalDate date = LocalDate.now();
Date date3 = new Date(1673740800000L);
Set<PlanDay> setPlans = new HashSet<>();
Plans plans = new Plans(1, setPlans);
BigDecimal price = new BigDecimal(8.00);
Meds meds = new Meds(1, "Brufen", price, "Pain", 200, date, setPlans);
when(medsRepo.getReferenceById(meds.getMedsId())).thenReturn(meds);
int pillNumber = meds.getPillNumber();
List<PlanDay> planList3 = new ArrayList<PlanDay>();
PlanDay planDay3 = new PlanDay(1, date3, "Tuesday", plans, meds, 50000);
planList3.add(planDay3);
String expected3 = saveService.savePlans(planList3);
assertThat(expected3).isEqualTo("Error: No piils available (Existing Pills: " + pillNumber + ")");
}
When it gets in * String expected3 = saveService.savePlans(planList3);* it stops and prints the error.
The method:
public String savePlans(List<PlanDay> plans) throws Error {
//long planIdVerify = plans.get(0).getPlanDaysId();
Date firstDate = plans.get(0).getPlanDate();
long todayMili = System.currentTimeMillis();
long dateLimitMili = firstDate.getTime() + 604800000;
long planId = plans.get(0).getPlans().getPlanId();
Plans plansWithId = new Plans();
plansWithId.setPlanId(planId);
plansRepo.save(plansWithId);
for (int i = 0; i < plans.size(); i++) {
long planDateInMili = plans.get(i).getPlanDate().getTime();
//long planIdMultiVerify = plans.get(i).getPlanDaysId();
if (planDateInMili <= dateLimitMili && todayMili<planDateInMili ) {
PlanDay planDay = plans.get(i);
long medsId = planDay.getMeds().getMedsId();
int medsToTake = planDay.getMedsToTake();
int pillNumber = medsRepo.getReferenceById(medsId).getPillNumber();
int pillUpdate = pillNumber - medsToTake;
Meds updatePlanDay = medsRepo.findById(medsId).get();
if (pillUpdate > 0) {
updatePlanDay.setPillNumber(pillUpdate);
} else {
return "Error: No piils available (Existing Pills: " + pillNumber + ")";
}
planDayRepo.save(planDay);
} else {
return "Week time interval not correct/Invalid planId (only one plan can be saved)";
}
}
return "Saved Successfully";
}
and my entities:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "meds")
#JsonIgnoreProperties(value = { "days" })
public class Meds {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long medsId;
#Column
private String medsName;
#Column
private BigDecimal price;
#Column
private String category;
#Column
private int pillNumber;
#Column
#CreationTimestamp
private LocalDate medsDate;
#OneToMany(mappedBy = "meds", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
#OnDelete(action = OnDeleteAction.CASCADE)
private Set<PlanDay> days = new HashSet<PlanDay>();
}
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "planDay")
#JsonIgnoreProperties(value = { "planDaysId" })
public class PlanDay {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long planDaysId;
#Column
private Date planDate;
#Column
private String weekday;
#ManyToOne
#JoinColumn(name = "planId", nullable = false)
private Plans plans;
#ManyToOne
#JoinColumn(name = "medsId", nullable = false)
private Meds meds;
#Column
private int medsToTake;
}
I have been looking for a solution and the orElse() method was one of the options but I can't make it work.. What would be a solution for this problem?
Kind Regards.

MedsRepo is a MockBean when you call medsRepo.findById(medsId) it will return an empty optional because you have no when for that method.
int pillNumber = medsRepo.getReferenceById(medsId).getPillNumber(); //extract the Meds as a variable and keep using this
int pillUpdate = pillNumber - medsToTake;
Meds updatePlanDay = medsRepo.findById(medsId).get(); //trying to get the same as you did above
Should be
Meds updatePlanDay = medsRepo.getReferenceById(medsId);
int pillNumber = updatePlanDay.getPillNumber();
int pillUpdate = pillNumber - medsToTake;
//Meds updatePlanDay = medsRepo.findById(medsId).get(); no longer needed
Also on a different note you should look into the difference between findById and getReferenceById and what happens when there is no Meds with that medsId

Related

How to set and save Date object

I am writing a JPA application and I have a Date object that needs to be set and then saved in the database.
Here's an example:
#Embeddable
public class Semester {
#Column(name = "is_started",
columnDefinition = "tinyint(1)",
nullable = false)
private Boolean isStarted;
#Column(name = "is_finished",
columnDefinition = "tinyint(1)",
nullable = false)
private Boolean isFinished;
#Column(name = "starting_date")
private Date startingDate;
#Column(name = "register_deadline_date")
private Date registerDeadlineDate;
}
I want to know How to Set a Date object to pass to my entity:
Should it be something like:
System.out.println("Enter Year: ");
String year = new Scanner(System.in).next();
System.out.println("Enter month: ");
String month = new Scanner(System.in).next();
System.out.println("Enter day: ");
String day = new Scanner(System.in).next();
Date startingDate = new Date(day, month, year);
Semester semester = new Semester();
semester.setStartingDate(startingDate);
repository.save(semester);
I did this but this constructor either doesn't work anymore or I am doing something wrong. Thanks in advance.
I succeeded at that.
Maybe, cause is that you didn't write #Entity,#Table(name = "foo").
#Setter
#Getter
#Table(name = "foo") // your name of Table
#Entity
public class Semester {
#Id
private Long id;
#Column(name = "starting_date")
private Date startingDate;
#Override
public String toString() {
return "id : "+id +",startingDate : "+ startingDate;
}
}
Repository interface
#Repository
public interface FooRepo extends JpaRepository<Semester, Long> {
}
execute class
#Component
public class FooExecute {
#Autowired
FooRepo fooRepo;
#Autowired
FooRepo repository;
public void execute() {
Date startingDate = new Date(121, 8, 29);
Semester semester = new Semester();
semester.setId(2L);
semester.setStartingDate(startingDate);
semester = repository.save(semester);
System.out.println("result:"+semester.toString());
//result:id : 2,startingDate : 2021-09-29
}
}

how to add subquery into specification in Java

I wish to have subquery, which provides me filtering actors by name.
I have a rest controller's method, which returns list of actors as JSON from movie base on movieId. I try to add filters as specification, but I have no idea how to write proper query. Base on "Spring Data JPA Specification for a ManyToMany Unidirectional Relationship" I found solution for subquery, which returns me all actors to proper movie base on movieId. Now I try to write this query.
Actor entity
#Data
#NoArgsConstructor
#Entity
#Table(name = "actors")
public class Actor implements Serializable {
private static final long serialVersionUID = 6460140826650392604L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "actor_id")
private Long actorId;
#Column(name = "first_name")
private String firstName;
#ManyToMany(mappedBy = "actors")
#ToString.Exclude
private List<Movie> movie = new ArrayList<>();
#JsonIgnore
public List<Movie> getMovie() {
return this.movie;
}
}
Movie entity
#Data
#Entity
#NoArgsConstructor
#Table(name = "movies")
public class Movie implements Serializable {
private static final long serialVersionUID = 3683778473783051508L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "movie_id")
private Long movieId;
private String title;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(name = "movies_actors"
, joinColumns = { #JoinColumn(name = "movie_id") }
, inverseJoinColumns = { #JoinColumn(name = "actor_id") })
private List<Actor> actors = new ArrayList<>();
#JsonIgnore
public List<Actor> getActors() {
return this.actors;
}
}
//Rest Controller
#CrossOrigin(origins = "http://localhost:3000")
#RestController
#RequestScope
#RequestMapping("/rest")
public class ActorRestController {
private ActorService actorService;
private MovieService movieService;
#Autowired
public ActorRestController(ActorService actorService, MovieService movieService) {
this.actorService = actorService;
this.movieService = movieService;
}
.
.
.
#GetMapping("movies/{movieId}/actors")
public ResponseEntity<Page<Actor>> getAllActorsFromMovieByIdMovie(#PathVariable(name = "movieId") Long movieId, Pageable pageable) {
Optional<Movie> movieFromDataBase = movieService.findMovieById(movieId);
if (movieFromDataBase.isPresent()) {
return new ResponseEntity<>(actorService.findAllActors(ActorSpec.query(movieId), pageable), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
.
.
}
// Specification for actor
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ActorSpec {
public static Specification<Actor> query(final Long movieId) {
return (root, query, cb) -> {
query.distinct(true);
Subquery<Movie> movieSubQuery = query.subquery(Movie.class);
Root<Movie> movie = movieSubQuery.from(Movie.class);
Expression<List<Actor>> actors = movie.get("actors");
movieSubQuery.select(movie);
movieSubQuery.where(cb.equal(movie.get("movieId"), movieId), cb.isMember(root, actors));
return cb.exists(movieSubQuery);
};
}
}
I would like, my code will return filtered actors by name ex.:
http://localhost:8080/rest/movies/48/actors?name=Collin
will return me
{ "actorId": 159,
"firstName": "Collin",
"lastName": "Konopelski",
"age": 21
},
but in case I do not sent any request param (http://localhost:8080/rest/movies/48/actors), let program return me all actors. I don't want to create new endpoint only for #Requestparam cause, this one is used by UI created in React.
Thanks!
Ok I found,
My solution:
RestController
#GetMapping("movies/{movieId}/actors")
public ResponseEntity<Page<Actor>> getAllActorsFromMovieByIdMovie(#PathVariable(name = "movieId") Long movieId,
#RequestParam(name = "name", required = false) String name,
Pageable pageable) {
Optional<Movie> movieFromDataBase = movieService.findMovieById(movieId);
if (movieFromDataBase.isPresent()) {
return new ResponseEntity<>(actorService.findAllActors(ActorSpec.query(movieId ,name), pageable), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
Specification
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ActorSpec {
public static Specification<Actor> query(final Long movieId, String name) {
return (root, query, cb) -> {
Predicate predicateMovieID = getPredicateByMovieId(movieId, root, query, cb);
if (Strings.isNotBlank(name)) {
Predicate a = cb.and(predicateMovieID, cb.equal(root.get("firstName"), name));
Predicate b = cb.and(predicateMovieID, cb.equal(root.get("lastName"), name));
return cb.or(a,b);
}
return cb.and(predicateMovieID);
};
}
private static Predicate getPredicateByMovieId(Long movieId, Root<Actor> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
query.distinct(true);
Subquery<Movie> movieSubQuery = query.subquery(Movie.class);
Root<Movie> movie = movieSubQuery.from(Movie.class);
Expression<List<Actor>> actors = movie.get("actors");
movieSubQuery.select(movie);
movieSubQuery.where(cb.equal(movie.get("movieId"), movieId), cb.isMember(root, actors));
return cb.exists(movieSubQuery);
}
}

Why would you use a public interface within a java db entity?

I found this code snippet while looking at other projects and I was wondering on the benefit of having a public interface within a java pojo. Why should you use it as seen in the below example. Is the below use considered a best practice? Is there a catch with using an interface liek this?
#Data
#NoArgsConstructor
#Entity
#Table(name = "customer_mapping", schema = "billing")
public class CustomerMapping {
public interface createCustomerMapping {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonProperty("customerMappingId")
private Integer id;
#Column(length=10)
#NotNull(groups = { createCustomerMapping.class })
#NotEmpty(groups = { createCustomerMapping.class })
#Size(groups = { createCustomerMapping.class }, min = 4, max = 4)
private String issuerCode;
#Column(length=10)
#NotNull(groups = { createCustomerMapping.class })
#NotEmpty(groups = { createCustomerMapping.class })
private String offerCode;
#NotNull
private Long customerId;
#CreationTimestamp
private LocalDateTime createdTs;
private String createdBy;
#UpdateTimestamp
private LocalDateTime updatedTs;
private String updatedBy;
public CustomerMapping(String offerCode) {
this.offerCode = offerCode;
}
public CustomerMapping(String issuerCode, String offerCode) {
this.issuerCode = issuerCode;
this.offerCode = offerCode;
}
public CustomerMapping(String issuerCode, String offerCode, Long customerId) {
this.issuerCode = issuerCode;
this.offerCode = offerCode;
this.customerId = customerId;
}
}
From what I know an interface is used to define a contract so I'm familiar with the implementation in using it via a library of code or if two teams needs to co-operate. But in the above example, its unclear to me.

OrmLite Complex query on 3 tables using QueryBuilder

I am trying to do a query on three tables by using QueryBuilder from OrmLite.
My problem is that my final query returns no results, while doing the query only for Info, InfoFenomeno or Instruccion do return results.
public List<PasoInstruccion> consultar(Request request) {
InfoRequest infoRequest = (InfoRequest) request;
ArrayList<PasoInstruccion> pasos = new ArrayList<>();
List<PasoInstruccion> pasosResult = null;
try {
QueryBuilder<Info, Long> infoQuery = LocalDBHelper.getInstance(context).getInfoDao().queryBuilder();
QueryBuilder<InfoFenomeno, Long> fenomenoQuery = LocalDBHelper.getInstance(context).getInfoFenomenoDao().queryBuilder();
fenomenoQuery.where()
.eq(InfoFenomeno.COLUMN_FENOMENO, infoRequest.getFenomeno());
infoQuery.join(fenomenoQuery);
QueryBuilder<Instruccion, Long> instruccionQuery = LocalDBHelper.getInstance(context).getInstruccionDao().queryBuilder();
instruccionQuery.where()
.eq(Instrucciones.COLUMN_NIVEL_AFECTACION, infoRequest.getNivelAfectacion())
.and()
.eq(Instrucciones.COLUMN_CATEGORIA_INFO, infoRequest.getCategoria())
.and()
.eq(Instrucciones.COLUMN_AMBIENTE_INFO, infoRequest.getSituacion());
QueryBuilder<PasoInstruccion, Long> pasoInstruccionQuery = LocalDBHelper.getInstance(context).getPasoInstruccionDao().queryBuilder();
instruccionQuery.join(infoQuery);
pasoInstruccionQuery.join(instruccionQuery);
pasosResult = pasoInstruccionQuery.query();
} catch (SQLException e) {
e.printStackTrace();
}
return pasosResult;
}
The structure on the DB is like this (simplified):
public class Info {
#DatabaseField(id = true, columnName = Infos.COLUMN_ID)
private long id;
#DatabaseField(columnName = Infos.COLUMN_NOMBRE)
private String nombre;
#ForeignCollectionField(eager = true, columnName = Infos.COLUMN_FENOMENO)
private ForeignCollection<InfoFenomeno> infoFenomenos;
#ForeignCollectionField(eager = true, columnName = Infos.COLUMN_INSTRUCCION)
private ForeignCollection<Instruccion> pInstrucciones;
}
public class InfoFenomeno {
#DatabaseField(generatedId = true, columnName = InfoFenomeno.COLUMN_ID)
private long id;
#DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = InfoFenomeno.COLUMN_INFO)
private Info info;
#DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = InfoFenomeno.COLUMN_FENOMENO)
private Fenomeno fenomeno;
}
public class Instruccion {
#DatabaseField(generatedId = true)
private long id;
#DatabaseField(columnName = Instrucciones.COLUMN_NIVEL_AFECTACION)
private String nivelAfectacionString;
#DatabaseField(columnName = Instrucciones.COLUMN_CATEGORIA_INFO)
private String categoriaInformacionString;
#DatabaseField(columnName = Instrucciones.COLUMN_AMBIENTE_INFO)
private String ambienteInformacionString;
#ForeignCollectionField(eager = true)
private ForeignCollection<PasoInstruccion> pPasosInstruccion;
#DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = Instrucciones.COLUMN_INFO)
private Info info;
}
public class PasoInstruccion {
#DatabaseField(id = true, columnName = PasoInstrucciones.COLUMN_ID)
private long secuencia;
#DatabaseField(columnName = PasoInstrucciones.COLUMN_NOMBRE)
private String nombre;
#DatabaseField(columnName = PasoInstrucciones.COLUMN_INSTRUCCION, foreignAutoRefresh = true, foreign = true)
private Instruccion instruccion;
}
Values in InfoRequest parameter are right.
May be that I am not using QueryBuilder the right way?
EDIT: SQL Statement
SELECT `pasoInstrucciones`.* FROM `pasoInstrucciones` INNER JOIN `instrucciones` ON `pasoInstrucciones`.`_instruccion` = `instrucciones`.`id` INNER JOIN `infos` ON `instrucciones`.`_info` = `infos`.`_id` INNER JOIN `infoFenomeno` ON `infos`.`_id` = `infoFenomeno`.`_info` WHERE ((`instrucciones`.`_nivelAfectacion` = 'BAJO' AND `instrucciones`.`_categoriaInfo` = 'ANTES' ) AND `instrucciones`.`_ambienteInfo` = 'HOGAR' ) AND (`infoFenomeno`.`_fenomeno` = 6 )
Thanks in advance.

comparing time in sql server through hibernate

I am trying to compare time through hibernate in SQL Server 2008.
The following code returns this error : The data types time and datetime are incompatible in the less than or equal to operator.
crit = session.createCriteria(ObdBlackoutHours.class);
Criterion start = Restrictions.le("blackoutStart", new Date());
Criterion end = Restrictions.gt("blackoutEnd",new Date());
List list = crit.add(Restrictions.conjunction().add(start).add(end))
.list();
if(list.isEmpty())
return false;
else
return true;
The table design is the following:
CREATE TABLE [dbo].[obd_blackout_hours](
[id] [int] NOT NULL,
[blackout_end] [time](7) NOT NULL,
[blackout_start] [time](7) NOT NULL)
I understand that the db contains only 10:17:37 and what I am passing is something like this Thu Nov 14 10:17:37 IST 2013 which it is unable to compare. I tested the same code in mysql which seems to be working very fine. But SQL Server 2008 is creating the problem. I also tried passing
currentDate = new SimpleDateFormat("HH:mm:ss").parse(new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()));
and
new ObdBlackoutHours(1,new Date(),new Date()).getBlackoutStart()
instead of the just the Date() object. This also fails. How should I compare time and get results.
The following is the entity class
#Entity
#Table(name = "obd_blackout_hours", schema = "dbo", catalog = "IVR_Data")
public class ObdBlackoutHours implements java.io.Serializable {
private int id;
private Date blackoutStart;
private Date blackoutEnd;
private Set<Service> services = new HashSet<Service>(0);
public ObdBlackoutHours() {
}
public ObdBlackoutHours(int id, Date blackoutStart, Date blackoutEnd) {
this.id = id;
this.blackoutStart = blackoutStart;
this.blackoutEnd = blackoutEnd;
}
public ObdBlackoutHours(int id, Date blackoutStart, Date blackoutEnd,
Set<Service> services) {
this.id = id;
this.blackoutStart = blackoutStart;
this.blackoutEnd = blackoutEnd;
this.services = services;
}
#Id
#Column(name = "id", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#Temporal(TemporalType.TIME)
#Column(name = "blackout_start", nullable = false, length = 16)
public Date getBlackoutStart() {
return this.blackoutStart;
}
public void setBlackoutStart(Date blackoutStart) {
this.blackoutStart = blackoutStart;
}
#Temporal(TemporalType.TIME)
#Column(name = "blackout_end", nullable = false, length = 16)
public Date getBlackoutEnd() {
return this.blackoutEnd;
}
public void setBlackoutEnd(Date blackoutEnd) {
this.blackoutEnd = blackoutEnd;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "obdBlackoutHours")
public Set<Service> getServices() {
return this.services;
}
public void setServices(Set<Service> services) {
this.services = services;
}
}
Refer to the following blog:
http://blogs.msdn.com/b/jdbcteam/archive/2010/04/08/using-time-and-date-data-types-part-1-what-time-is-it.aspx
Need to add the following to your hibernate connection url string
I am not sure if it's true/false just play with it.
sendTimeAsDateTime=false

Categories

Resources