#java #spring #spring-boot #hibernate #spring-mvc
#java #весна #spring-boot #спящий режим #spring-mvc
Вопрос:
Я закончил создание простого проекта Spring-boot, в который я могу вводить пользователей, и с помощью команды Get он возвращает мне имя (из списка идентичных имен) с самой старой датой ввода. К сожалению, каждый раз, когда я запрашиваю Get, он возвращает эту ОШИБКУ:
D:>curl -G localhost:8080/demo/first -d name=Biagio
{"timestamp":"2020-10-05T08:52:34.741 00:00","status":500,"error":"Internal Server Error","message":"","path":"/demo/first"}
В терминале весенней загрузки у меня эта ОШИБКА:
Biagio
2020-10-05 10:52:34.722 ERROR 8860 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.EmptyResultDataAccessException: No entity found for query; nested exception is javax.persistence.NoResultException: No entity found for query] with root cause
Даже когда я пытаюсь ОПУБЛИКОВАТЬ / добавить, я получаю сообщение о том, что он сохранен в БД, но на самом деле ничего не сохранил
Ниже я добавляю все заинтересованные стороны:
AccessingDataMysqlApplication.java
package com.example.accessingdatamysql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
public class AccessingDataMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataMysqlApplication.class, args);
}
}
MainController.java
package com.example.accessingdatamysql.rest;
import javax.persistence.NoResultException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.service.UserService;
@RestController
@RequestMapping("/demo")
public class MainController {
@Autowired
private UserService userService;
@Transactional
//@RequestMapping(value = "/add/", method = RequestMethod.POST)
@PostMapping(path="/demo/add")
public String addNewUser(@PathVariable("name") String name, @PathVariable("email") String email,
@PathVariable("surname") String surname) {
UserDto n = new UserDto();
n.setName(name);
n.setSurname(surname);
n.setEmail(email);
userService.create(n);
return "User Saved in DB";
}
@SuppressWarnings({ "rawtypes", "unchecked" })
//@RequestMapping(value = "/fetchUser/{name}", method = RequestMethod.GET)
@GetMapping("/demo/first")
public ResponseEntity<UserDto> fetchUser(@PathVariable("name") String name) {
System.out.println(name);
try {
UserDto namefound = userService.findFirstByName(name);
System.out.println("Name found");
ResponseEntity<UserDto> user = new ResponseEntity<UserDto>(namefound, HttpStatus.OK);
return user;
} catch(NoResultException ne) {
System.out.println("User not found");
return new ResponseEntity("User not found with name : " name, HttpStatus.NOT_FOUND);
}
}
}
UserService.java
package com.example.accessingdatamysql.service;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
@Service
public interface UserService {
UserDto findFirstByName(String name);
void create(UserDto user);
}
UserServiceImpl.java
package com.example.accessingdatamysql.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
import com.example.accessingdatamysql.util.UserMapper;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
UserMapper mapper;
@Override
public UserDto findFirstByName(String name) {
UserEntity entity = userRepository.findFirstByName(name);
return mapper.toDtoMapper(entity);
}
@Override
public void create(UserDto user) {
UserEntity entity = mapper.toEntityMapper(user);
userRepository.create(entity);
}
}
UserMapper.java
package com.example.accessingdatamysql.util;
import org.mapstruct.Mapper;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
@Mapper(componentModel = "spring")
public interface UserMapper {
public UserEntity toEntityMapper (UserDto user);
public UserDto toDtoMapper (UserEntity userEntity);
}
UserRepository.java
package com.example.accessingdatamysql.repo;
import org.springframework.stereotype.Repository;
import com.example.accessingdatamysql.model.UserEntity;
@Repository
public interface UserRepository {
UserEntity findFirstByName(String name);
void create(UserEntity entity);
}
UserRepositoryImpl.java
package com.example.accessingdatamysql.service;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Component;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
@Component
public class UserRepositoryImpl implements UserRepository {
private final EntityManager em;
public UserRepositoryImpl(EntityManager entityManager) {
this.em = entityManager;
}
@Override
public UserEntity findFirstByName(String name) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<UserEntity> criteria = builder.createQuery(UserEntity.class);
Root<UserEntity> root = criteria.from(UserEntity.class);
criteria.select(root).where(builder.equal(root.get("name"), name));
criteria.orderBy(builder.asc(root.get("timestamp")));
TypedQuery<UserEntity> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
@Override
// per la creazione//
public void create(UserEntity entity) {
em.persist(entity);
}
}
UserDto.java
package com.example.accessingdatamysql.model;
import java.io.Serializable;
import java.sql.Timestamp;
public class UserDto implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7621330660870602403L;
/**
*
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
private Timestamp timestamp;
private String email;
private String surname;
}
Если вам также нужно, я мог бы предоставить User.java и файл pom, но у pom нет проблем, так как все зависимости верны.
Комментарии:
1. Я бы попросил использовать postman или другой инструмент для тестирования вместо curl, и в соответствии с вашей ошибкой в классе обслуживания в CriteriaBuilder идентификатор пользователя не найден. похоже, проблема в диспетчере сущностей. вы могли бы найти точную проблему, но правильный код dubug или TDD. Другой вариант — использовать CrudRepository или JpaRepository
2. Вы неправильно используете spring data jpa. Вы должны использовать
JpaRepository
. Также я вижу, что вы используете@PathVariable
запрос POST для отправки нескольких пользовательских полей в URL. Почему вы не используете@RequestBody
3. Привет, Аджит! вы правы, на самом деле лучше использовать @RequestParam
Ответ №1:
Ваш create
метод недействителен. И из-за этого вы фактически не можете получить некоторые данные. Вы только вызвали persist
метод, но вам также нужно позвонить flush
, чтобы фактически записать это в БД. Фрагмент кода может выглядеть следующим образом:
@Transactional
@Override
public void create(UserEntity entity) {
if (!em.contains(entity)) {
em.persist(entity);
em.flush();
}
}
Комментарии:
1. Привет, Evg! не были бы вы достаточно любезны, чтобы показать мне, куда поместить этот фрагмент кода??
2. Конечно, он должен быть помещен внутри вашего
public void create(UserEntity entity)
метода в вашемUserRepositoryImpl
классе. ps. Просто обновил ответ.3. Когда я использую ваш метод, я выхожу из этой ошибки:
.InvalidDataAccessApiUsageException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead; nested exception is java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead] with root cause java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
4. Хорошо, я снова обновлю ответ, проверьте его. Смысл здесь в том, чтобы делегировать обработку транзакций Spring вместо ручной обработки.
5. Даже вставка изменения ничего не меняет
Ответ №2:
Ну, вы не получаете результата в своем запросе, но принудительно выполняете getSingleResult()
его. Вы можете использовать CrudRepository из Spring, это немного проще.
Комментарии:
1. Привет, Милго! Большое вам спасибо за ваш ответ, к сожалению, я не могу использовать Crud для различных требований, которые были наложены на меня