First time trying out GraphQL, so please excuse if it is a basic fix.
https://i.stack.imgur.com/Hwf8Q.png
My API is used to show some mock data of departures from Heathrow. The API should return all the departures which are displayed in the import.sql file. This is running a h2 in memory DB using Spring. My application.properites:
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:mem:lhrdata
graphql.servlet.mapping=/graphql
graphql.servlet.enabled=true
graphql.servlet.corsEnabled=true
graphiql.enabled=true
graphiql.endpoint=/graphql
graphiql.mapping=graphiql
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.defer-datasource-initialization=true
Entity > Departure.java
package com.LHRDepartures.LHROUT.entity;
import javax.persistence.*;
import java.util.Arrays;
import java.util.List;
#Entity
public class Departure {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String destination;
private Float arrival_time;
private String airline;
private String aircraft_make;
private String aircraft_model;
private String terminal;
public Departure() {
}
public Departure(Long id, String destination, Float arrival_time, String airline, String aircraft_make, String aircraft_model, String terminal) {
this.id = id;
this.destination = destination;
this.arrival_time = arrival_time;
this.airline = airline;
this.aircraft_make = aircraft_make;
this.aircraft_model = aircraft_model;
this.terminal = terminal;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public Float getArrival_time() {
return arrival_time;
}
public void setArrival_time(Float arrival_time) {
this.arrival_time = arrival_time;
}
public String getAirline() {
return airline;
}
public void setAirline(String airline) {
this.airline = airline;
}
public String getAircraft_make() {
return aircraft_make;
}
public void setAircraft_make(String aircraft_make) {
this.aircraft_make = aircraft_make;
}
public String getAircraft_model() {
return aircraft_model;
}
public void setAircraft_model(String aircraft_model) {
this.aircraft_model = aircraft_model;
}
public String getTerminal() {
return terminal;
}
public void setTerminal(String terminal) {
this.terminal = terminal;
}
}
Mutator
package com.LHRDepartures.LHROUT.mutator;
import com.LHRDepartures.LHROUT.entity.Departure;
import com.LHRDepartures.LHROUT.exception.DepartureNotFoundException;
import com.LHRDepartures.LHROUT.repository.DepartureRepository;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import org.springframework.stereotype.Component;
import java.util.Optional;
public class Mutation implements GraphQLMutationResolver {
private DepartureRepository departureRepository;
public Mutation(DepartureRepository departureRepository){
this.departureRepository = departureRepository;
}
public boolean deleteDeparture(Long ID){
departureRepository.deleteById(ID);
return true;
}
/*
public Departure updateTerminal(Integer newTerminal, Long Id){
Optional<Departure> optionalDeparture =
departureRepository.findById(Id);
if(optionalDeparture.isPresent()){
Departure departure = optionalDeparture.get();
// departureRepository.setName(newTerminal);
departureRepository.save(departure);
return departure;
} else {
throw new DepartureNotFoundException("Departure not found!", Id);
} */
}
Repository
package com.LHRDepartures.LHROUT.repository;
import com.LHRDepartures.LHROUT.entity.Departure;
import org.springframework.data.repository.CrudRepository;
public interface DepartureRepository extends CrudRepository<Departure, Long> {
}
Query
package com.LHRDepartures.LHROUT.resolver;
import com.LHRDepartures.LHROUT.entity.Departure;
import com.LHRDepartures.LHROUT.repository.DepartureRepository;
import org.springframework.stereotype.Component;
#Component
public class Query {
private DepartureRepository departureRepository;
public Query(DepartureRepository departureRepository){
this.departureRepository = departureRepository;
}
public Iterable<Departure> findAllDepartures() {
return departureRepository.findAll();
}
}
Service
package com.LHRDepartures.LHROUT.service;
import com.LHRDepartures.LHROUT.entity.Departure;
import org.springframework.stereotype.Service;
import java.util.List;
public interface DepartureService {
List<Departure> retrieveDeparture();
}
Controller
package com.LHRDepartures.LHROUT.web;
import com.LHRDepartures.LHROUT.entity.Departure;
import com.LHRDepartures.LHROUT.service.DepartureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class DepartureController {
private DepartureService departureService;
#Autowired
public void setDepartureService(DepartureService departureService){
this.departureService = departureService;
}
#GetMapping("/departure")
public ResponseEntity<List<Departure>> getAllDeparture(){
List<Departure> list = departureService.retrieveDeparture();
return new ResponseEntity<List<Departure>>(list, HttpStatus.OK);
}
}
GraphQL schema:
type Departure{
id: ID!
destination : String!
arrival_time : Float!
airline : String!
aircraft_make : String
aircraft_model : String
terminal : String!
}
type Query {
findAllDepartures: [Departure]
}
type Mutation {
deleteDeparture(id:ID) : Boolean
updateTerminal(newTerminal : String, id:ID!): Departure!
}
Import.sql
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (1, 'LAX - Los Angeles Intl.', '1234', 'British Airways', 'AIRBUS', 'A380', '5');
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (2, 'JFK - New York John F. Kennedy Intl.', '1345', 'British Airways', 'BOEING', '777-300', '5');
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (3, 'MAN - Manchester Intl.', '1400', 'British Airways', 'AIRBUS', 'A319', '5');
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (4, 'FRA - Frankfurt Intl.', '1521', 'Lufthansa', 'AIRBUS', 'A319', "3');
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (5, 'CPT - Cape Town Intl.', '1605', 'Virgin Atlantic', 'BOEING', '787-900', '2');
INSERT INTO departure (id, destination, arrival_time, airline, aircraft_make, aircraft_model, terminal) VALUES (6, 'LAX - Los Angeles Intl.', '1634', 'British Airways', 'BOEING', '777-300', '5');
I know there's a lot there, but I'm quite stuck. Any help appreciated.
At the moment you have no code that will glue your graphql server and business logic together.
Fortunately, Spring boot provides seamless integration GraphQL integration with their Spring Boot for GraphQL project.
In order to start using it, just add the following dependency to your build tool.
implementation 'org.springframework.boot:spring-boot-starter-graphql'
Then, you need to add your schema to the following place:
resources/graphql/schema.graphqls
Your schema definition looks good, so it will work when added into this place
Lastly, you need to define a Controller which will bind your business logic to the graphql server.
import com.example.graphql.departure.model.Departure;
import com.example.graphql.departure.model.DepartureRepository;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
#Controller
public class DepartureController {
private final DepartureRepository departureRepository;
public DepartureController(DepartureRepository departureRepository) {
this.departureRepository = departureRepository;
}
#QueryMapping
public Iterable<Departure> findAllDepartures() {
return departureRepository.findAll();
}
}
Check how #QueryMapping annotation is used in order to define a valid graphql query.
Then, if you run everything, you should be able to see the results.
Take a look at this sample project for a reference https://github.com/CaptainAye/graphql-sample
Related
I am making an Android app that has a database. I am able to create all the tables I need but need to populate some tables with static data. I tried doing this with a migration but cannot get the code to run as I expect. This data is needed for that app to run and will not change. Is a migration that runs immediately after the database is created the correct way to do this? I want to be sure that the rows only get created once and the app will never need to check for their existence after the database is created.
All the relevant classes are below. Let me know if any more details are needed. TIA!
Status
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
#Entity(tableName = "Status", indices = { #Index(value = {"Name"}, unique = true) })
public class Status
{
#PrimaryKey(autoGenerate = true)
public int Id;
#NonNull
public String Name;
}
StatusEnum
public enum StatusEnum
{
New(1, "New"),
InProgress(2, "In Progress"),
Closed(3, "Closed");
public final int Id;
public final String Name;
StatusEnum(int id, String name)
{
Id = id;
Name = name;
}
}
StaticDataMigration
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
#RequiresApi(api = Build.VERSION_CODES.O)
#Database(entities = { Status.class }, version = 2, exportSchema = false)
public abstract class StaticDataMigration extends RoomDatabase
{
public static final Migration MIGRATION_1_2 = new Migration(1, 2)
{
#Override
public void migrate(SupportSQLiteDatabase database)
{
sql = "INSERT INTO Status VALUES ";
for (StatusEnum enumType : StatusEnum.values())
{
sql = sql + String.format("(%d, %s),", enumType.Id, enumType.Name);
}
sql = removeLastChar(SQL);
database.beginTransaction();
database.execSQL(sql);
database.endTransaction();
Room.databaseBuilder(getApplicationContext(), MyDatabase.class, "MyDatabase").addMigrations(MIGRATION_1_2).build();
}
//Room.databaseBuilder(Context, MyDatabase.class, "MyDatabase").addMigrations(MIGRATION_1_2).build();
//Database.mig(Context, MyDatabase., "MyDatabase").addMigrations(MIGRATION_1_2).build();
};
private static String removeLastChar(String s)
{
return (s == null || s.length() == 0) ? null : (s.substring(0, s.length() - 1));
}
}
I'm new to Springboot and making post/get requests, and I've been following a youtube tutorial to better understand it with postman. However, I've run into a problem while tinkering with the code, I'm trying to allow a post request for 2 entries
{
"name": "Hat",
"price": "$1"
}
however, whenever I try to send a get request it returns
{
"price": "null"
"name": "Hat"
}
I believe the problem is that the price is not being posted, thus the .orElse(null) is executing. I'm not sure why this is the case, and I would greatly appreciate the help. If any further information is needed let me know and I'll post it.
package com.example.demo.dao;
import com.example.demo.model.Person;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Repository("fakeDao") //class serves as a repository
public class FakePersonDataAcessService implements PersonDao{
private static List<Person> DB = new ArrayList<>();
#Override
public int insertPerson(Person/*BigDecimal*/ price, Person person) {
DB.add(new Person(price.getPrice(), person.getName()));
return 1;
}
#Override
public List<Person> selectAllPeople() {
return DB;
}
#Override
public Optional<Person> selectPersonByPrice(Person/*BigDecimal*/ price) {
return DB.stream()
.filter(person -> person.getPrice().equals(price)) //filters through the people and checks our DB to see if that person with that price exists
.findFirst();
}
#Override
public int deletePersonByPrice(Person/*BigDecimal*/ price) {
Optional<Person> personMaybe = selectPersonByPrice(price);
if (personMaybe.isEmpty()){
return 0;
}
DB.remove(personMaybe.get());
return 1;
}
#Override
public int updatePersonByPrice(Person/*BigDecimal*/ price, Person update) {
return selectPersonByPrice(price) //select the person
.map(person -> { //map the person
int indexOfPersonToUpdate = DB.indexOf(person);
if (indexOfPersonToUpdate >= 0){ //if the index of that person is >=0 we know that we have found that person
DB.set(indexOfPersonToUpdate, new Person(price.getPrice(), update.getName())); //set contents of that person to the new person that we just recieved from thc client
return 1; //return 1 if everything is fine
}
return 0; //otherwise we return 0 or if selectpersonbyprice is not present we dont do anyhthing and just return 0
})
.orElse(0);
}
}
package com.example.demo.api;
import com.example.demo.model.Person;
import com.example.demo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
#RequestMapping("api/v1/person")
#RestController
public class PersonController {
private final PersonService personService;
#Autowired
public PersonController(PersonService personService) {
this.personService = personService;
}
#PostMapping
public void addPerson(Person price,/*#Valid #NotNull Stringprice,*/#Valid #NotNull #RequestBody Person person){
personService.addPerson(price,/*price,*/ person);
}
#GetMapping
public List<Person> getAllPeople(){
return personService.getAllPeople();
}
#GetMapping(path = "{price}")
public Person getPersonByPrice(#PathVariable("price") Person/*BigDecimal*/ price){
return personService.getPersonByPrice(price) //after sending a get request with that price we will either return the person, OR if they don't exisist we return null
.orElse(null);
}
#DeleteMapping(path = "{price}")
public void deletePersonByPrice(#PathVariable("price") Person/*BigDecimal*/ price){
personService.deletePerson(price);
}
#PutMapping(path = "{price}")
public void updatePerson(#PathVariable("price") Person/*BigDecimal*/ price, #Valid #NotNull #RequestBody Person personToUpdate){
personService.updatePerson(price, personToUpdate);
}
}
package com.example.demo.dao;
import com.example.demo.model.Person;
import javax.swing.text.html.Option;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
//actual interface where we can define our operations allowed/contract for anyone who wants to implement this interface; and using dependecy injection we can change db easily
public interface PersonDao {
int insertPerson(Person price, Person person); //allows us to insert a person with a given price
/*
default int insertPerson(Person price, Person person){
String price = new String("$"); //without an price, its default is 0
return insertPerson(price, person);
}
*/
List<Person> selectAllPeople();
Optional<Person> selectPersonByPrice(Person/*BigDecimal*/ price);
int deletePersonByPrice(Person/*BigDecimal*/ price);
int updatePersonByPrice(Person/*BigDecimal*/ price, Person person);
}
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.UUID;
public class Person {
private final String price;
#NotBlank //name can't be blank
private final String name;
public Person(#JsonProperty("price") String /*BigDecimal*/ price,
#JsonProperty("name") String name) {
this.price = price;
this.name = name;
}
public String/*BigDecimal*/ getPrice() {
return price;
}
public String getName() {
return name;
}
}
package com.example.demo.service;
import com.example.demo.dao.PersonDao;
import com.example.demo.model.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Service
public class PersonService {
private final PersonDao personDao;
#Autowired
public PersonService(#Qualifier("fakeDao") PersonDao personDao) {
this.personDao = personDao;
}
public int addPerson(Person price,/*String price,*/ Person person){
return personDao.insertPerson(price,/*price,*/ person);
}
#GetMapping
public List<Person> getAllPeople(){
return personDao.selectAllPeople();
}
public Optional<Person> getPersonByPrice(Person/*BigDecimal*/ price){
return personDao.selectPersonByPrice(price);
}
public int deletePerson(Person/*BigDecimal*/ price){
return personDao.deletePersonByPrice(price);
}
public int updatePerson(Person/*BigDecimal*/ price, Person newPerson){
return personDao.updatePersonByPrice(price, newPerson);
}
}
For simplicity sake, I'll just keep my code limited to add and get APIs.
CHANGES IN CONTROLLER
Firstly, when retrieving the person by price, it will be a list and not Optional. The reason for the same is that multiple items( in this case, person) can be present at the same price.
Secondly,you are passing price as a Person and not as String, therefore that needs to be changed. After simplification , this becomes your controller for getting price by price
#GetMapping(path = "{price}")
public List<Person> getPersonByPrice(#PathVariable("price") String price) {
return personService.getPersonByPrice(price);
}
CHANGES IN FAKE PERSON DATA ACCESS SERVICE
Here , you need to iterate the entire list with the given price and whenever a Person matches it, it will be added to your required list .
#Override
public List<Person> selectPersonByPrice(String price) {
List<Person> p = new ArrayList<>();
Person person = new Person("", price);
for (Person temp : DB) {
if (temp.getPrice().equals(price)) {
p.add(temp);
}
}
return p;
}
Thus, your declaration of this method will also change in PersonService.
After implementing these changes and making a request to the get api, it is successfully returning an it
I'm building a project with spring boots, checking the status of the Internet through control, and I'm in the process of a DB connection.
I'm trying to do 'MyBatis', but there's an error.
This is a list of my directories:
MinitoringdataApplication.java
package com.smartcore.mn.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#MapperScan(basePackages = "com.smartcore.mn.springboot")
public class MinitoringdataApplication {
public static void main(String[] args) {
SpringApplication.run(MinitoringdataApplication.class, args);
}
}
ServletInitializer.java
package com.smartcore.mn.springboot;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MinitoringdataApplication.class);
}
}
ApiController.java
package com.smartcore.mn.springboot.controller;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.smartcore.mn.springboot.model.Member;
import com.smartcore.mn.springboot.service.MemberService;
#RestController
public class ApiController {
#Autowired
MemberService memberService;
#GetMapping(path = "/helloWorld")
public String helloWorld() {
return LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
#GetMapping(path = "/db")
public List<Member> selectAllMember() {
List<Member> members = memberService.getAllMember();
return members;
}
}
MemberMapper.interface
package com.smartcore.mn.springboot.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.smartcore.mn.springboot.model.Member;
#Mapper
public interface MemberMapper {
Member selectMemberById(Long id);
List<Member> selectAllMember();
void insertMember(Member member);
}
Member.java
package com.smartcore.mn.springboot.model;
import java.util.Date;
import org.apache.ibatis.type.Alias;
import com.smartcore.mn.springboot.Exception.IdPasswordNotMatchingException;
import lombok.Data;
#Data
#Alias("member")
public class Member {
private Long id;
private String email;
private String password;
private String name;
private Date registerDate;
public Member(String email, String password, String name, Date registerDate) {
this.email = email;
this.password = password;
this.name = name;
this.registerDate = registerDate;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public String getName() {
return name;
}
public Date getRegisterDate() {
return registerDate;
}
public void changePassword(String oldPassword, String newPassword) {
if (!password.equals(oldPassword))
throw new IdPasswordNotMatchingException();
this.password = newPassword;
}
}
MemberService.java
package com.smartcore.mn.springboot.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.smartcore.mn.springboot.mapper.MemberMapper;
import com.smartcore.mn.springboot.model.Member;
#Service
#Transactional
public class MemberService {
#Autowired
MemberMapper memberMapper;
public Member getMemberById(Long id) {
return memberMapper.selectMemberById(id);
}
public List<Member> getAllMember() {
return memberMapper.selectAllMember();
}
public void addMember(Member member) {
memberMapper.insertMember(member);
}
}
application.properties
spring.datasource.url=jdbc:mysql://localhost/mydb?serverTimezone=UTC&autoReconnection=true
spring.datasource.username=mydb
spring.datasource.password=mydb
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.type-aliases-package=com.smartcore.mn.springboot.model
logging.level.com.smartcore.mn.springboot.mapper=TRACE
MemberMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.smartcore.mn.springboot.mapper.MemberMapper">
<select id="selectMemberById" resultType="member">
SELECT *
FROM MEMBER
WHERE ID = #{id}
</select>
<select id="selectAllMember" resultType="member">
SELECT *
FROM MEMBER
</select>
<insert id="insertMember">
INSERT INTO MEMBER (EMAIL, PASSWORD, NAME, REGDATE)
VALUES (#{email}, #{password}, #{name}, #{registerDate})
</insert>
</mapper>
http://localhost:8080/helloworld is works normally.
But http://localhost:8080/db have see Error
I need your solution. Thank you in advance.
my TABLE
As mentioned in our discussion in comments, MyBatis is trying to map your NAME column in result-set to the registerDate argument in the Member constructor.
Since you did not specify paramName for each fields, the order of arg elements in the constructor is error-prone.
Try mapping your result-set to your constructor with correct ordered args:
Member(String email, String password, String name, Date registerDate) should match SELECT EMAIL, PASSWORD, NAME, REGDATE FROM MEMBER
or
Member(Long id, String email, String password, String name, Date registerDate) should match SELECT * FROM MEMBER
I have made a spring boot application connected to an angular front end. When the user enters a value into attendance id and hits submit on the form, this calls a method that updates the current value in the database using a HTTP PUT request.
However, the value is not being update despite break points showing the new value is being received and updated.
I am new to spring boot so any help is appreciated.
package com.example.demo.Attendance;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.transaction.Transactional;
import com.example.demo.AttendancePK.AttendancePK;
import com.example.demo.AttendanceType.AttendanceType;
import com.example.demo.LessonRun.LessonRun;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Transactional
#Entity
public class Attendance {
#EmbeddedId
private AttendancePK id;
#ManyToOne
#JoinColumn(name="attendance_type", insertable = false, updatable=false)
private AttendanceType attendanceType;
#ManyToOne
#JsonIgnore
#JoinColumn(name="lesson_run_id", insertable = false, updatable=false)
private LessonRun lessonRun;
public LessonRun getLessonRun() {
return lessonRun;
}
public void setLessonRun(LessonRun lessonRun) {
this.lessonRun = lessonRun;
}
public AttendanceType getAttendanceType() {
return attendanceType;
}
public void setAttendanceType(AttendanceType attendanceType) {
this.attendanceType = attendanceType;
}
public Attendance(AttendancePK id, AttendanceType attendanceType, LessonRun lessonRun) {
super();
this.id = id;
this.attendanceType = attendanceType;
this.lessonRun = lessonRun;
}
public Attendance() {
}
public AttendancePK getId() {
return id;
}
public void setId(AttendancePK id) {
this.id = id;
}
}
My controller
#RequestMapping(value="/attendance/{attendanceId}/student/{studentId}/lessonrun/{lessonRunId}",method = RequestMethod.PUT)
public void updateAttendance(#PathVariable int attendanceId, #PathVariable int studentId, #PathVariable int lessonRunId, #RequestBody int attendanceTypeId) {
AttendancePK id = new AttendancePK(attendanceId, studentId,lessonRunId);
Attendance attendanceInDB = attendanceService.getAttendancebyId(id);
// attendanceInDB.setAttendanceType(int.getAttendanceType());
attendanceService.updateAttendance(attendanceInDB, attendanceTypeId);
}
My Service
package com.example.demo.Attendance;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.AttendancePK.AttendancePK;
import com.example.demo.AttendanceType.AttendanceType;
import com.example.demo.AttendanceType.AttendanceTypeRepository;
#Service
public class AttendanceService {
#Autowired
private AttendanceRepository attendanceRepository;
#Autowired
private AttendanceTypeRepository attendanceTypeRepository;
public List<Attendance> getAllAttendanceRecs() {
List<Attendance> attendanceList = new ArrayList<>();
attendanceRepository.findAll().forEach(attendanceList::add);
return attendanceList;
}
public Attendance getAttendancebyId(AttendancePK id) {
Optional<Attendance> optionalAttendance = attendanceRepository.findById(id);
if (optionalAttendance.isPresent()) {
return optionalAttendance.get();
}
return null;
}
public void updateAttendance(Attendance attendanceInDB, int attendanceTypeId) {
Optional<AttendanceType> attendanceType = attendanceTypeRepository.findById(attendanceTypeId);
if (attendanceType.isPresent()) {
attendanceInDB.setAttendanceType(attendanceType.get());
attendanceRepository.save(attendanceInDB);
}
}
}
the breakpoint results show the value is updated shown here
but MySQL database doesn't reflect this
i need to update tow columns inside my table (Job this table is joint with two other tables employees and job-history)one of them is the primary key, but i get error, if someone can help!
package com.touati.org.model;
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.List;
/**
* The persistent class for the jobs database table.
*
*/
#Entity
#Table(name="jobs")
#NamedQuery(name="Job.findAll", query="SELECT j FROM Job j")
public class Job implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="JOB_ID")
private String jobId;
#Column(name="JOB_TITLE")
private String jobTitle;
#Column(name="MAX_SALARY")
private BigDecimal maxSalary;
#Column(name="MIN_SALARY")
private BigDecimal minSalary;
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="job")
private List<Employee> employees;
//bi-directional many-to-one association to JobHistory
#OneToMany(mappedBy="job")
private List<JobHistory> jobHistories;
public Job() {
}
public String getJobId() {
return this.jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getJobTitle() {
return this.jobTitle;
}
public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}
public BigDecimal getMaxSalary() {
return this.maxSalary;
}
public void setMaxSalary(BigDecimal maxSalary) {
this.maxSalary = maxSalary;
}
public BigDecimal getMinSalary() {
return this.minSalary;
}
public void setMinSalary(BigDecimal minSalary) {
this.minSalary = minSalary;
}
public List<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public Employee addEmployee(Employee employee) {
getEmployees().add(employee);
employee.setJob(this);
return employee;
}
public Employee removeEmployee(Employee employee) {
getEmployees().remove(employee);
employee.setJob(null);
return employee;
}
public List<JobHistory> getJobHistories() {
return this.jobHistories;
}
public void setJobHistories(List<JobHistory> jobHistories) {
this.jobHistories = jobHistories;
}
public JobHistory addJobHistory(JobHistory jobHistory) {
getJobHistories().add(jobHistory);
jobHistory.setJob(this);
return jobHistory;
}
public JobHistory removeJobHistory(JobHistory jobHistory) {
getJobHistories().remove(jobHistory);
jobHistory.setJob(null);
return jobHistory;
}
}
my controller: here when i try to look for all job in the data base it works fine, also if i try to update juste the title of the job it works fine to but in case that i try to set a new primary key for the job table it gives me error here my controller.
package com.touati.org.model;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
#Controller // This means that this class is a Controller
#RequestMapping(path="/project") // This means URL's start with /demo (after Application path)
public class MainController {
#GetMapping(path="/job")
public #ResponseBody Iterable<Job> getAllJob() {
// This returns a JSON or XML with the users
return jobRepository.findAll();
}
#GetMapping(path="/job/{jobId}")
public #ResponseBody String getJob(#PathVariable String jobId) {
Job job = jobRepository.findOne(jobId);
try {
job.setJobTitle("manager");
job.setJobId("test1");
jobRepository.save(job);
}
catch (Exception ex) {
return "Error updating the job: " + ex.toString();
}
return "Job succesfully updated!";
}
i got this error,
Error updating the user: org.springframework.orm.jpa.JpaSystemException: identifier of an instance of com.touati.org.model.Job was altered from test to test1; nested exception is org.hibernate.HibernateException: identifier of an instance of com.touati.org.model.Job was altered from test to test1
Thank you for your help.
Altering the PK of an entity is not permitted - if you really have to do it, you should delete, and recreate it.
Reference (an older question) : JPA Hibernate - changing the primary key of an persisted object