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);
}}
Related
I am trying to update my database (postgresql) in my spring boot app with some form information that I will get from an angular 8 form. How can I complete the code below to do so ?
PS : I have no access to the front devs, so no access to the angular code.
My Entity :
#Entity
#Data
#Table(name = "person")
#AllArgsConstructor
#NoArgsConstructor
public class PersonEntity implements java.io.Serializable {
#Id
#Column(name = "id_person")
private int idPerson;
#Column(name = "name")
private String name;
#Column(name = "alive")
private Boolean alive;
}
My Mapping class :
#Data
public class PersonForm {
#NotBlank
private String idPerson;
#NotBlank
private String name;
private boolean alive;
}
My Repository :
#Repository
public interface IPersonRepository extends JpaRepository<PersonEntity, String> {
}
My Controller :
#RequestMapping(value = "person")
public class PersonController {
private final PersonService personService;
public PersonController(PersonService personService) {this.personService = personService;}
#PostMapping(value = "savePerson")
#ResponseBody
public ResponseEntity<PersonEntity> savePerson(#RequestBody final PersonForm form) {
return ?
}
}
My Service :
#Transactional
#Service
public class PersonService {
#Autowired
private IPersonRepository personRepository;
public IPersonRepository(IPersonRepository personRepository) {
this.personRepository = personRepository;
}
Maybe this is enough to work.
Have others ways to do it, this is only example that complements your line of thought.
If you get a compilation error or another error, let me know :)
First you need create your object PersonEntity and sent it to your service.
#RequestMapping(value = "person")
public class PersonController {
private final PersonService personService;
public PersonController(PersonService personService) {this.personService = personService;}
#PostMapping(value = "savePerson")
#ResponseBody
public ResponseEntity<PersonEntity> savePerson(#RequestBody final PersonForm form) {
PersonEntity entity = new PersonEntity(form);
entity = personService.save(entity);
return ResponseEntity.ok(entity);
}
}
In your service, you will call the save method from repository implementation.
#Transactional
#Service
public class PersonService {
#Autowired
private IPersonRepository personRepository;
public IPersonRepository(IPersonRepository personRepository) {
this.personRepository = personRepository;
}
public PersonEntity save(PersonEntity entity) {
return personRepository.save(entity);
}
}
After it you will create ResponseEntity in the method PersonController.savePerson
I'm using Neo4j to create graphs. The below codes is an example for spring data Neo4j. I can save a node entity when no id property value is provided.
But how to save a node entiry with a specific id property value?
Model Class:
#Data
#NodeEntity
public class Person {
#Id
#GeneratedValue
private Long id;
private String name;
private String title;
#Relationship(type = "ACTED_IN")
private List<Movie> movies = new ArrayList<>();
}
Repository Class
public interface PersonRepository extends Neo4jRepository<Person, Long> {
#Query("MATCH (n:Person {name:{name}}) RETURN n")
List<Person> findByName(#Param("name") String name);
}
Controller Class
#RestController
#RequestMapping("/person")
public class PersonController {
#Autowired
private PersonRepository personRepository;
#PostMapping("/save")
public Map save(#RequestBody Person person) {
Map resultMap = new HashMap();
String code = "200";
String msg = "success";
// It can save success when no id property value is provided
Person savedPerson = personRepository.save(person);
resultMap.put("code", code);
resultMap.put("msg", msg);
resultMap.put("data", savedPerson);
return resultMap;
}
}
I have tried it successfully and can be easily done provide the "id" should be
String not Long
Domain/DAO class:
#Id
#GeneratedValue(strategy = Neo4JCustomIdStrategy.class)
String id;
Repository Class:
#Repository
public interface PersonRepository extends Neo4jRepository<Person, String>{
}
And lastly, custom implementation of Strategy:
public class Neo4JCustomIdStrategy implements IdStrategy {
#Override
public Object generateId(Object entity) {
return String.valueOf(entity.hashCode());
}
}
The library I am using is spring-data-neo4j
I'm trying to build simple REST for purchases I need 2 methods. The first method should show all purchases sorted by date. The second one removes all purchases for specified date I made a method to add and to get all purchases. Now I'm stuck.
#Entity
#Table (name="purchase")
public class Purchase {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#CreationTimestamp
#Temporal(TemporalType.DATE)
#Column(name="createat")
private Date created;
#Column(name="price")
private BigDecimal price;
#Column(name="currency")
private String currency;
#Repository
public interface PurchaseRepository extends JpaRepository<Purchase, Long>
{
}
#Service
public class PurchaseService {
#Autowired
private PurchaseRepository purchaseRepository;
public void addPurchase(Purchase purchase) {
purchaseRepository.save(purchase);
}
public List<Purchase> getAllPurchase() {
List<Purchase> purchase = new ArrayList<>();
purchaseRepository.findAll().forEach(purchase::add);
return purchase;
}
}
#RestController
public class PurchaseController {
#Autowired
private PurchaseService purchaseService;
#PostMapping("/purchase")
public void addPurchase(#RequestBody Purchase purchase) {
purchaseService.addPurchase(purchase);
}
#RequestMapping("/purchase")
public List<Purchase> getAllTopics() {
return purchaseService.getAllPurchase();
}
}
What I need:
1. method to sort my List sorted by date
2. method that removes all purchases for specified date
You can use Spring Data JPA features in these cases.
Add the following methods to PurchaseRepository:
List<Purchase> findAllByOrderByCreatedAsc();
long deleteByCreated(Date created);
And after all, Spring is going to generate an appropriate query based on a method name.
I got it
long deleteByCreated(Date date);
#Transactional
public long deleteAllByDate(Date date){
return purchaseRepository.deleteByCreated(date);
}
#RequestMapping(method=RequestMethod.DELETE, value="/purchasess/{date}")
public long findAllByCreatedBetween(#DateTimeFormat(pattern="yyyy-MM-dd")
#PathVariable Date date){
return purchaseService.deleteAllByDate(date);
}
I try select data from the table by a filter with Spring Data JPA Specification I think what my implementation is correct, But it doesn't work. Help me please understand my mistake and fix my example.
I have very strange SQL query in log :
select phone0_.id as id1_0_, phone0_.note as note2_0_, phone0_.number as number3_0_, phone0_.operator_login as operator4_0_, phone0_.operator_pass as operator5_0_, phone0_.operator_name as operator6_0_, phone0_.operator_url as operator7_0_, phone0_.reg_date as reg_date8_0_, phone0_.status as status9_0_ from phone phone0_ where 0=1 limit ?
In the end: where 0=1 it's crash my mind. Where did that come from?
Here I fill CriteriaBuilder if filter field not null. I expect to get correctly built Specification object and send it to findAll(Specifications.where(specification), Pageable p) method. But something incorrect.
My repo and specification impl:
public interface PhoneRepository extends CrudRepository<Phone, Integer>, JpaRepository<Phone, Integer>, JpaSpecificationExecutor<Phone> {
class PhoneSpecification implements Specification<Phone> {
private final #NonNull PhoneService.PhoneFilter filter;
public PhoneSpecification(#NonNull PhoneService.PhoneFilter filter) {
this.filter = filter;
}
#Override
public Predicate toPredicate(Root<Phone> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate predicate = cb.disjunction();
if (nonNull(filter.getId())) {
cb.disjunction().getExpressions().add(cb.equal(root.get("id"), filter.getId()));
}
if (nonNull(filter.getNote())) {
cb.disjunction().getExpressions().add(cb.like(root.get("note"), filter.getNote()));
}
if (nonNull(filter.getNumber())) {
cb.disjunction().getExpressions().add(cb.like(root.get("number"), filter.getNumber()));
}
if (nonNull(filter.getStatus())) {
cb.disjunction().getExpressions().add(cb.like(root.get("status"), filter.getStatus()));
}
if (nonNull(filter.getOpName())) {
cb.disjunction().getExpressions().add(cb.like(root.get("operatorName"), filter.getOpName()));
}
if (nonNull(filter.getOpLogin())) {
cb.disjunction().getExpressions().add(cb.like(root.get("operatorAccLogin"), filter.getOpLogin()));
}
if (nonNull(filter.getOpPassword())) {
cb.disjunction().getExpressions().add(cb.like(root.get("operatorAccPassword"), filter.getOpPassword()));
}
if (nonNull(filter.getRegFrom()) && nonNull(filter.getRegTo())) {
cb.disjunction().getExpressions().add(cb.between(root.get("regDate"), filter.getRegFrom(), filter.getRegTo()));
}
return predicate;
}
}
}
This is service level:
#Service
public class PhoneService {
#Autowired
private PhoneRepository phoneRepository;
public Phone get(int id) {
Phone phone = phoneRepository.findOne(id);
return nonNull(phone) ? phone : new Phone();
}
public Page<Phone> list(#NonNull PhoneFilter filter) {
PhoneSpecification specification = new PhoneSpecification(filter);
return phoneRepository.findAll(Specifications.where(specification), filter.getPageable());
}
#Data
public static class PhoneFilter {
private Pageable pageable;
private Integer id;
private Timestamp regFrom;
private Timestamp regTo;
private String number;
private String opLogin;
private String opPassword;
private String opName;
private String status;
private String note;
}
}
And entity
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "phone")
#ToString(exclude = {"accounts"})
#EqualsAndHashCode(exclude = {"accounts"})
public class Phone {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToMany(mappedBy = "phone", cascade = CascadeType.DETACH)
private Collection<SocialAccount> accounts;
#Column(name = "reg_date")
private Timestamp regDate;
#Column(name = "number")
private String number;
#Column(name = "operator_url")
private String operatorUrl;
#Column(name = "operator_login")
private String operatorAccLogin;
#Column(name = "operator_pass")
private String operatorAccPassword;
#Column(name = "operator_name")
private String operatorName;
#Column(name = "status")
private String status;
#Column(name = "note")
private String note;
}
I find the mistake.
Method CriteriaBuilder.disjunction() this is factory and each time when I call him I got new Predicate object.
This implementation CriteriaBuilderImpl:
public Predicate disjunction() {
return new CompoundPredicate(this, BooleanOperator.OR);
}
Be careful with it.
I have a CrudRepository that is supposed to make a query with an array (findByIn). In my repository tests it works, but when I try to use the query in my service, it doesn't work. Could someone explain why it doesn't work? Here is my setup (excluding some code irrelevant to the question)
Database model:
#Entity
#Table(name="Place")
public class Place implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "placeId", nullable = false)
private Long placeId;
#Column(name = "owner", nullable = false)
private String owner;
public Long getPlaceId() {
return placeId;
}
public void setPlaceId(Long placeId) {
this.placeId = placeId;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
}
Repository:
#Repository
public interface PlaceRepository extends CrudRepository<Place, Long> {
List<Place> findByPlaceIdIn(Long[] placeId);
}
Service (this is the part not working):
#Service
public class PlaceService {
#Autowired
private PlaceRepository placeRepository;
public List<Place> getPlaces(Long[] placeIds) {
return placeRepository.findByPlaceIdIn(placeIds);
}
}
The problem is that in my service placeRepository.findByPlaceIdIn(placeIds) returns 0 objects if placeIds contains more than one item. If placeIds contains just one item, the query works fine. I tried replacing return placeRepository.findByPlaceIdIn(placeIds) with this piece of code that does the query for every array item one by one (this actually works, but I'd like to get the query work as it should):
ArrayList<Place> places = new ArrayList<Place>();
for (Long placeId : placeIds) {
Long[] id = {placeId};
places.addAll(placeRepository.findByPlaceIdIn(id));
}
return places;
I know that the repository should work, because I have a working test for it:
public class PlaceRepositoryTest {
#Autowired
private PlaceRepository repository;
private static Place place;
private static Place place2;
private static Place otherUsersPlace;
#Test
public void testPlacesfindByPlaceIdIn() {
place = new Place();
place.setOwner(USER_ID);
place2 = new Place();
place2.setOwner(USER_ID);
place = repository.save(place);
place2 = repository.save(place2);
Long[] ids = {place.getPlaceId(), place2.getPlaceId()};
assertEquals(repository.findByPlaceIdIn(ids).size(), 2);
}
}
I also have another repository for other model, which also uses findByIn and it works fine. I can't see any relevant difference between the repositories. I thought it might offer some more details to show the working repository, so I included it below:
Database model:
#Entity
#Table(name="LocalDatabaseRow")
#JsonIgnoreProperties(ignoreUnknown=false)
public class LocalDatabaseRow implements Serializable {
public LocalDatabaseRow() {}
public LocalDatabaseRow(RowType rowType) {
this.rowType = rowType;
}
public enum RowType {
TYPE1,
TYPE2
};
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
#JsonProperty("id")
private Long id;
#JsonProperty("rowType")
#Column(name = "rowType")
private RowType rowType;
public Long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public RowType getRowType() {
return rowType;
}
public void setRowType(RowType rowType) {
this.rowType = rowType;
}
}
Repository:
#Repository
public interface LocalDatabaseRowRepository extends CrudRepository<LocalDatabaseRow, Long> {
List<LocalDatabaseRow> findByRowTypeAndUserIdIn(RowType type, String[] userId);
}
try using a list instead :
findByPlaceIdIn(List placeIdList);
You have a typo in your code (the repository declaration in the service):
#Autowired
private placeRepository placeRepository;
Should be:
#Autowired
private PlaceRepository placeRepository;