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
}
}
Related
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
I have 2 databases. One is set up and and it works. After I add second db I am having following error entityManageFactory error. Schema-validation: missing table [hibernate_sequence].
My db schema looks like this: db schema screenshot
I have two classes for two tables:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Entity(name = "nightly_rate_amounts")
#Table(name = "nightly_rate_amounts")
public class BookedNightlyRate {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "bnr_meta_id")
private Long id;
#Column(name = "unit_uuid")
private UUID unitUuid;
private LocalDate firstLiveDate;
private LocalDate date;
private BigDecimal amount;
#Column(name = "currency_code")
private String currencyCode;
public ImmutableTriple<UUID, LocalDate, String> toUnitDateCurrencyKey() {
return new ImmutableTriple<>(unitUuid, date, currencyCode);
}
public ImmutablePair<UUID, String> toUnitCurrencyKey() {
return new ImmutablePair<>(unitUuid, currencyCode);
}
}
and:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Entity(name = "unit_attributes")
#Table(name = "unit_attributes")
public class BookedUnitAttributes {
#Id
#Column(name = "unit_uuid")
private UUID unitUuid;
#Column(name = "first_date_available")
private LocalDate firstLiveDate;
}
and Repository files:
public interface BookedNightlyRatesDao extends CrudRepository<BookedNightlyRate, Long> {
#Query(value = "SELECT DISTINCT bnr.unit_uuid as unitUuid, bnr.date, bnr.amount, bnr.currency_code as currencyCode " +
"FROM nightly_rate_amounts AS bnr " +
"WHERE bnr.unit_uuid IN (<unitUuids>) AND (bnr.date BETWEEN :fromDate AND :toDate)", nativeQuery = true)
List<BookedNightlyRate> findBookedNightlyRates(#Param("unitUuids") List<String> unitUuids, #Param("fromDate") LocalDate fromDate, #Param("toDate") LocalDate toDate);
#Query(value = "SELECT DISTINCT opb.unit_uuid as unitUuid, opb.date, opb.amount, opb.currency_code as currencyCode " +
"FROM opb_nightly_rate_amounts AS opb " +
"JOIN opb_sync_enabled_for_unit AS sync ON opb.unit_uuid = sync.unit_uuid WHERE sync.enabled = 1 AND opb.is_active = 1 " +
"AND sync.unit_uuid IN (<unitUuids>) AND (opb.date BETWEEN :fromDate AND :toDate)", nativeQuery = true)
List<BookedNightlyRate> findOPBRates(#Param("unitUuids") List<String> unitUuids, #Param("fromDate") LocalDate fromDate, #Param("toDate") LocalDate toDate);
}
second interface:
public interface BookedUnitAttributesDao extends CrudRepository<BookedUnitAttributes, UUID> {
#Query(value = "SELECT ua.unit_uuid as unitUuid, ua.first_date_available as firstLiveDate " +
"FROM unit_attributes AS ua " +
"WHERE ua.unit_uuid IN (<unitUuids>)", nativeQuery = true)
List<BookedUnitAttributes> findUnitAttributes(#Param("unitUuids") List<String> unitUuids);
}
I am rewriting my db from jdbi to jpa. So Data classes didn't have any annotations and I refactored my model files regarding it queries in repository files.
Since you add two database Spring dosn't know what kind of database it connect. You have to exactly showed what kind of database you want to connect.
You might confiugure connection with two different database here is example of working with JdbcTemplate connection.
#Configuration
#ComponentScan("uz.dbo.dbocallcenter")
#PropertySource("classpath:database.properties")
public class Config2 {
#Autowired
Environment environment;
private final String DRIVER = "driver";
private final String URL1 = "url1";
private final String USER1 = "dbusername1";
private final String PASSWORD1 = "dbpassword1";
private final String URL2 = "url2";
private final String USER2 = "dbusername2";
private final String PASSWORD2 = "dbpassword2";
private DataSource dataSource1() {
return getDataSource(URL1, USER1, PASSWORD1);
}
private DataSource dataSource2() {
return getDataSource(URL2, USER2, PASSWORD2);
}
private DataSource getDataSource(String url1, String user1, String password1) {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setUrl(environment.getProperty(url1));
driverManagerDataSource.setUsername(environment.getProperty(user1));
driverManagerDataSource.setPassword(environment.getProperty(password1));
driverManagerDataSource.setDriverClassName(environment.getProperty(DRIVER));
return driverManagerDataSource;
}
#Bean(name = "jdbcTemplate2")
public JdbcTemplate jdbcTemplate2() {
return new JdbcTemplate(dataSource2());
}
#Bean(name = "jdbcTemplate1")
public JdbcTemplate jdbcTemplate1() {
return new JdbcTemplate(dataSource1());
}
}
you have to do with JpaRepository connection. More precisely you can gain knowledge about this source
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
Here is also good explanation how to connect two differnet database in one spring boot project
https://www.baeldung.com/spring-data-jpa-multiple-databases
In my database I have two tables airport and calendar connected by foreight key airport_id. I want to get json response with data from two tables for the determined airport_id=273
For example I want to get data for Airport with airport_id and Calendar with foreight key airport_id equels 273. Actually, I've got empty response from localhost:8080. I didn't get any error, just a blank page, like on the picture below. What I do wrong? Thank you in advance!
Airport.java
#Entity
#Table(name = "airport")
public class Airport {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer airport_id;
#Column(name = "departureAirport")
private String departureAirport;
#Column(name = "destinationAirport")
private String destinationAirport;
#OneToMany(mappedBy = "airport")
#JsonManagedReference("airport")
private List<Calendar> calendars; ....
Calendar.java
#Entity
#Table(name = "calendar")
public class Calendar {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer calendar_id;
#Column(name = "departureTime")
private Time departureTime;
#Column(name = "destinationTime")
private Time destinationTime;
#ManyToOne(targetEntity = Airport.class)
#JoinColumn(name = "airport_id")
#JsonBackReference("airport")
private Airport airport; ....
CalendarController.java
public class CalendarController {
#Autowired
CalendarService calendarService;
#Autowired
AirportService airportService;
#GetMapping(value = "/search/{airport_id}")
public List<Calendar> getCalendars(#PathVariable("airport_id") Integer airport_id) {
Airport airport = airportService.findOne(airport_id);
return calendarService.findOne(airport);
}}
CalendarRepository.java
public interface CalendarRepository extends CrudRepository<Calendar, Integer> {
Calendar getOne(int calendar_id);
List<Calendar> findByAirport(Airport airport_id);
}
CalendarService.java
public interface CalendarService {
List<Calendar> findOne(Airport airport_id);
}
CalendarServiceImpl.java
#Service
public class CalendarServiceImpl implements CalendarService {
#Autowired
CalendarRepository repository;
#Autowired
AirportRepository airportRepository;
#Override
public List<Calendar> getCalendars(Integer airport_id) {
Airport airport = airportRepository.getOne(airport_id);
return repository.findByAirport(airport);
}}
Update
AirpostService.java
public interface AirportService {
Airport findOne(int airport_id);
}
AirportRepository.java
public interface AirportRepository extends CrudRepository<Airport, Integer> {
Airport getOne(Integer airport_id);
}
The problem is not your Hibernate, but your Controller. You just need to add the #Responsebody annotation to your method. The #ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON.
#GetMapping(value = "/search/{airport_id}")
#ResponseBody
public List<Calendar> getCalendars(#PathVariable("airport_id") Integer airport_id) {
Airport airport = airportService.findOne(airport_id);
return calendarService.findOne(airport);
}}
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
Situation: NotificationProfile entity has collection of NotificationProfileIntegration entities which has embedded IntegrationNotificationCutOff. It is legacy database and i cannot modify it. Someone thought it is a good idea to store time as "HH:mm" strings, but i need to work with date objects. That is the reason why i have these convert callbacks and transient date fields.
When i do (for existing profile entity)
entityManager.merge(profile);
I expect that #PreUpdate is called on NotificationProfileIntegration and dates are converted to their string representation and persisted to DB. Instead #PostLoad method is called first and #PreUpdate is called after.
So if i set something in cutOff instance it is never persisted, because in #PostLoad method new instance of cutOffs is created because it is null due to this feature of hibernate
When all of the values in an #Embedded object are null, Hibernate will
set the field in the parent object to null.
How can i handle this situation? Thank you.
#Entity
#Table(name = "NOTIFICATION_PROFILES")
public class NotificationProfile extends AbstractEntity<Long> {
#OneToMany(mappedBy = "notificationProfile", cascade = CascadeType.ALL, orphanRemoval = true)
private Collection<NotificationProfileIntegration> profileIntegrations;
....
}
#Entity
#Table(name = "NOTIFICATION_PROFILE_INTEG")
public class NotificationProfileIntegration extends AbstractEntity<Long> {
#Embedded
private IntegrationNotificationCutOff cutOffs;
#Embedded
private IntegrationNotificationAverageCount averageShipments;
#PostLoad
public void initEmbeded() {
if (cutOffs == null) {
cutOffs = new IntegrationNotificationCutOff();
}
if (averageShipments == null) {
averageShipments = new IntegrationNotificationAverageCount();
}
cutOffs.convertToDates();
}
#PreUpdate
#PrePersist
private void formatCutOffs() {
if (cutOffs != null) {
cutOffs.convertToValues();
}
}
}
#Embeddable
public class IntegrationNotificationCutOff {
#Column(name = "NPI_CUT_OFF_TIME_MON")
private String monday;
#Column(name = "NPI_CUT_OFF_TIME_TUE")
private String tuesday;
#Column(name = "NPI_CUT_OFF_TIME_WED")
private String wednesday;
#Column(name = "NPI_CUT_OFF_TIME_THU")
private String thursday;
#Column(name = "NPI_CUT_OFF_TIME_FRI")
private String friday;
#Column(name = "NPI_CUT_OFF_TIME_SAT")
private String saturday;
#Column(name = "NPI_CUT_OFF_TIME_SUN")
private String sunday;
#Transient
private Date mondayDate;
#Transient
private Date tuesdayDate;
#Transient
private Date wednesdayDate;
#Transient
private Date thursdayDate;
#Transient
private Date fridayDate;
#Transient
private Date saturdayDate;
#Transient
private Date sundayDate;
public void convertToDates() {
SimpleDateFormat dateFormat = getDateFormat();
mondayDate = nullSafeConvert(monday, dateFormat);
tuesdayDate = nullSafeConvert(tuesday, dateFormat);
wednesdayDate = nullSafeConvert(wednesday, dateFormat);
thursdayDate = nullSafeConvert(thursday, dateFormat);
fridayDate = nullSafeConvert(friday, dateFormat);
saturdayDate = nullSafeConvert(saturday, dateFormat);
sundayDate = nullSafeConvert(sunday, dateFormat);
}
public void convertToValues() {
SimpleDateFormat dateFormat = getDateFormat();
monday = nullSafeFormat(mondayDate, dateFormat);
tuesday = nullSafeFormat(tuesdayDate, dateFormat);
wednesday = nullSafeFormat(wednesdayDate, dateFormat);
thursday = nullSafeFormat(thursdayDate, dateFormat);
friday = nullSafeFormat(fridayDate, dateFormat);
saturday = nullSafeFormat(saturdayDate, dateFormat);
sunday = nullSafeFormat(sundayDate, dateFormat);
}
private String nullSafeFormat(Date date, SimpleDateFormat dateFormat) {
if (date == null) {
return null;
}
return dateFormat.format(date);
}
private SimpleDateFormat getDateFormat() {
return new SimpleDateFormat("HH:mm");
}
private Date nullSafeConvert(String day, SimpleDateFormat dateFormat) {
if (day == null) {
return null;
}
try {
return dateFormat.parse(day);
} catch (ParseException e) {
return null;
}
}
}
EDIT
It seems that embedding does not have any efect on this behavior. When i refactor it to single entity problem is still here: after calling createOrUpdate - select is triggered before an update and my change to entity is somewhere "lost"