When I run my Spring Boot application, everything works fine: Hibernate generates tables and populates them with a LoadDatabase configuration class.
I have a TestController that I use to test whether my SQL queries defined in repository classes work correctly. Once I try to go to a test endpoint and query some data from the database, I get the following error:
java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.JdbcMapping.getJdbcValueBinder()" because "jdbcMapping" is null
What can it be? Some problems with model classes? Please, write a comment if I should provide more information.
LoadDatabase
class:
@Configuration
public class LoadDatabase {
@Bean
CommandLineRunner initDatabase(CleanerRepository cleanerRepository,
RoomRepository roomRepository,
CleanerScheduleRecordRepository cleanerScheduleRecordRepository) {
/* HOTEL CLEANERS */
Cleaner cleaner1 = new Cleaner(1, "John", "", "Doe");
Cleaner cleaner2 = new Cleaner(2, "Petro", "Olehovich", "Petrov");
Cleaner cleaner3 = new Cleaner(3, "Karl", "", "Johnson");
/* ROOMS ON THE FLOOR #1 */
Room floor1_room1 = new Room(101, "155-44-33", RoomType.ONE_GUEST, true);
Room floor1_room2 = new Room(102, "111-22-33", RoomType.ONE_GUEST, true);
Room floor1_room3 = new Room(103, "124-54-22", RoomType.ONE_GUEST, true);
Room floor1_room4 = new Room(104, "125-43-22", RoomType.TWO_GUESTS, true);
Room floor1_room5 = new Room(105, "123-65-93", RoomType.TWO_GUESTS, true);
Room floor1_room6 = new Room(106, "173-43-32", RoomType.TWO_GUESTS, true);
Room floor1_room7 = new Room(107, "184-77-22", RoomType.THREE_GUESTS, true);
Room floor1_room8 = new Room(108, "164-29-54", RoomType.THREE_GUESTS, true);
Room floor1_room9 = new Room(109, "175-88-99", RoomType.THREE_GUESTS, true);
/* ROOMS ON THE FLOOR #2 */
Room floor2_room1 = new Room(201, "237-44-33", RoomType.ONE_GUEST, true);
Room floor2_room2 = new Room(202, "211-22-33", RoomType.ONE_GUEST, true);
Room floor2_room3 = new Room(203, "224-54-22", RoomType.ONE_GUEST, true);
Room floor2_room4 = new Room(204, "225-43-22", RoomType.TWO_GUESTS, true);
Room floor2_room5 = new Room(205, "223-65-93", RoomType.TWO_GUESTS, true);
Room floor2_room6 = new Room(206, "273-43-32", RoomType.TWO_GUESTS, true);
Room floor2_room7 = new Room(207, "284-77-22", RoomType.THREE_GUESTS, true);
Room floor2_room8 = new Room(208, "264-29-54", RoomType.THREE_GUESTS, true);
Room floor2_room9 = new Room(209, "275-88-99", RoomType.THREE_GUESTS, true);
/* ROOMS ON THE FLOOR #3 */
Room floor3_room1 = new Room(301, "355-44-33", RoomType.ONE_GUEST, true);
Room floor3_room2 = new Room(302, "311-22-33", RoomType.ONE_GUEST, true);
Room floor3_room3 = new Room(303, "324-54-22", RoomType.ONE_GUEST, true);
Room floor3_room4 = new Room(304, "325-43-22", RoomType.TWO_GUESTS, true);
Room floor3_room5 = new Room(305, "323-65-93", RoomType.TWO_GUESTS, true);
Room floor3_room6 = new Room(306, "373-43-32", RoomType.TWO_GUESTS, true);
Room floor3_room7 = new Room(307, "384-77-22", RoomType.THREE_GUESTS, true);
Room floor3_room8 = new Room(308, "364-29-54", RoomType.THREE_GUESTS, true);
Room floor3_room9 = new Room(309, "375-88-99", RoomType.THREE_GUESTS, true);
/* CLEANERS' SCHEDULE RECORDS */
CleanerScheduleRecord record1 = new CleanerScheduleRecord(cleaner1, DayOfWeek.SUNDAY, 1);
CleanerScheduleRecord record2 = new CleanerScheduleRecord(cleaner1, DayOfWeek.MONDAY, 2);
CleanerScheduleRecord record3 = new CleanerScheduleRecord(cleaner1, DayOfWeek.TUESDAY, 3);
CleanerScheduleRecord record4 = new CleanerScheduleRecord(cleaner1, DayOfWeek.WEDNESDAY, 1);
CleanerScheduleRecord record5 = new CleanerScheduleRecord(cleaner1, DayOfWeek.THURSDAY, 2);
CleanerScheduleRecord record6 = new CleanerScheduleRecord(cleaner1, DayOfWeek.FRIDAY, 3);
CleanerScheduleRecord record7 = new CleanerScheduleRecord(cleaner1, DayOfWeek.SATURDAY, 1);
CleanerScheduleRecord record8 = new CleanerScheduleRecord(cleaner2, DayOfWeek.SUNDAY, 3);
CleanerScheduleRecord record9 = new CleanerScheduleRecord(cleaner2, DayOfWeek.MONDAY, 1);
CleanerScheduleRecord record10 = new CleanerScheduleRecord(cleaner2, DayOfWeek.TUESDAY, 2);
CleanerScheduleRecord record11 = new CleanerScheduleRecord(cleaner2, DayOfWeek.WEDNESDAY, 3);
CleanerScheduleRecord record12 = new CleanerScheduleRecord(cleaner2, DayOfWeek.THURSDAY, 1);
CleanerScheduleRecord record13 = new CleanerScheduleRecord(cleaner2, DayOfWeek.FRIDAY, 2);
CleanerScheduleRecord record14 = new CleanerScheduleRecord(cleaner2, DayOfWeek.SATURDAY, 3);
CleanerScheduleRecord record15 = new CleanerScheduleRecord(cleaner3, DayOfWeek.SUNDAY, 2);
CleanerScheduleRecord record16 = new CleanerScheduleRecord(cleaner3, DayOfWeek.MONDAY, 3);
CleanerScheduleRecord record17 = new CleanerScheduleRecord(cleaner3, DayOfWeek.TUESDAY, 1);
CleanerScheduleRecord record18 = new CleanerScheduleRecord(cleaner3, DayOfWeek.WEDNESDAY, 2);
CleanerScheduleRecord record19 = new CleanerScheduleRecord(cleaner3, DayOfWeek.THURSDAY, 3);
CleanerScheduleRecord record20 = new CleanerScheduleRecord(cleaner3, DayOfWeek.FRIDAY, 1);
CleanerScheduleRecord record21 = new CleanerScheduleRecord(cleaner3, DayOfWeek.SATURDAY, 2);
return args -> {
cleanerRepository.saveAll(Arrays.asList(cleaner1, cleaner2, cleaner3));
roomRepository.saveAll(Arrays.asList(floor1_room1, floor1_room2, floor1_room3, floor1_room4, floor1_room5, floor1_room6, floor1_room7, floor1_room8, floor1_room9));
roomRepository.saveAll(Arrays.asList(floor2_room1, floor2_room2, floor2_room3, floor2_room4, floor2_room5, floor2_room6, floor2_room7, floor2_room8, floor2_room9));
roomRepository.saveAll(Arrays.asList(floor3_room1, floor3_room2, floor3_room3, floor3_room4, floor3_room5, floor3_room6, floor3_room7, floor3_room8, floor3_room9));
cleanerScheduleRecordRepository.saveAll(Arrays.asList(record1, record2, record3, record4, record5, record6, record7, record8, record9, record10, record11,
record12, record13, record14, record15, record16, record17, record18, record19, record20, record21));
};
}
}
TestController
class:
@Controller
@RequestMapping(path = "/test")
public class TestController {
private final AdministrationService administrationService;
@Autowired
public TestController(AdministrationService administrationService) {
this.administrationService = administrationService;
}
@GetMapping(path = "/")
public String areThereAvailableRooms() {
System.out.println(administrationService.areThereAvailableRooms());
System.out.println(administrationService.getCleanerInfoByDayAndFloor("MONDAY", 3));
return "hello";
}
}
AdministrationService
class:
@Service
public class AdministrationService {
private final CleanerService cleanerService;
private final GuestService guestService;
private final RoomService roomService;
@Autowired
public AdministrationService(CleanerService cleanerService, GuestService guestService, RoomService roomService) {
this.cleanerService = cleanerService;
this.guestService = guestService;
this.roomService = roomService;
}
public List<Guest> getGuestsInfoByRoomNumber(Integer roomNumber) {
return guestService.getGuestsInfoByRoom(roomNumber);
}
public List<Guest> getGuestsInfoByCity(String city) {
return guestService.getGuestsByCity(city);
}
public Cleaner getCleanerInfoByDayAndFloor(String day, Integer floorNumber) {
return cleanerService.getCleanerByFloorAndDay(DayOfWeek.valueOf(day), floorNumber);
}
public boolean areThereAvailableRooms() {
return roomService.areThereAvailableRooms();
}
public Long getNumberOfAvailableRooms() {
return roomService.getNumberOfAvailableRooms();
}
public void hireCleaner(Cleaner cleaner) {
cleanerService.hireNewCleaner(cleaner);
}
public void layOffCleaner(Cleaner cleaner) {
cleanerService.layOffCleaner(cleaner);
}
public void changeCleanerSchedule(Cleaner cleaner, String day, Integer floorNumber) {
cleanerService.changeCleanerSchedule(cleaner, DayOfWeek.valueOf(day), floorNumber);
}
public void checkInGuests(Guest... guests) {
checkInGuestsAndReserveRoom(guests);
}
public void checkOutGuestsByRoomNumber(Integer roomNumber) {
checkOutGuestsAndFreeUpRoom(roomNumber);
}
private void checkInGuestsAndReserveRoom(Guest... guests) {
String suitableRoomType = getSuitableRoomType(guests.length);
Integer roomNumber = roomService.findFirstAvailableRoomNumberDependingOnType(String.valueOf(suitableRoomType));
guestService.checkInGuestsInRoom(roomNumber, guests);
roomService.setAvailableToFalse(roomNumber);
}
private String getSuitableRoomType(int numberOfGuests) {
return switch (numberOfGuests) {
case (1) -> String.valueOf(RoomType.ONE_GUEST);
case (2) -> String.valueOf(RoomType.TWO_GUESTS);
case (3) -> String.valueOf(RoomType.THREE_GUESTS);
default ->
throw new NoAvailableRoomTypeException(String.format("There is no room for %s guests!", numberOfGuests));
};
}
private void checkOutGuestsAndFreeUpRoom(Integer roomNumber) {
guestService.checkOutGuestsFromRoom(roomNumber);
roomService.setAvailableToTrue(roomNumber);
}
}
CleanerRepository
interface:
@Repository
public interface CleanerRepository extends JpaRepository<Cleaner, Integer> {
@Query(value = "SELECT * FROM hotel_management_system.cleaner clnr JOIN hotel_management_system.cleaner_schedule_record csr on clnr.cleaner_id = csr.cleaner_cleaner_id" +
" WHERE csr.week_day=?1 AND csr.floor_number=?2", nativeQuery = true)
Optional<Cleaner> findCleanerByFloorAndDay(DayOfWeek day, Integer floorNumber);
}
EDIT: Model classes:
@Entity(name = "cleaner")
public class Cleaner {
@Id
@GeneratedValue
@Column(name = "cleaner_id")
private Integer cleanerID;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "middle_name")
private String middleName;
@Column(name = "last_name", nullable = false)
private String lastName;
@OneToMany(mappedBy = "cleaner", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CleanerScheduleRecord> scheduleRecords = new ArrayList<>();
public Cleaner() {
}
public Cleaner(Integer cleanerID, String firstName, String middleName, String lastName) {
this.cleanerID = cleanerID;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
public Integer getCleanerID() {
return cleanerID;
}
}
@Entity(name = "cleaner_schedule_record")
public class CleanerScheduleRecord {
@Id
@GeneratedValue
@Column(name = "record_id")
private Integer recordID;
@ManyToOne(fetch = FetchType.LAZY)
private Cleaner cleaner;
@Enumerated(EnumType.STRING)
@Column(name = "week_day", nullable = false)
private DayOfWeek dayOfWeek;
@Column(name = "floor_number", nullable = false)
private Integer floorNumber;
public CleanerScheduleRecord() {
}
public CleanerScheduleRecord(Cleaner cleaner, DayOfWeek dayOfWeek, Integer floorNumber) {
this.cleaner = cleaner;
this.dayOfWeek = dayOfWeek;
this.floorNumber = floorNumber;
}
}