Я делаю небольшое веб-приложение. В этом приложении я могу регистрировать новых пользователей. У пользователя есть один ролик, а у ролика может быть много пользователей.
Таблица пользователей
Таблица ролей
Если я сделаю INSERT, я хочу, чтобы столбец rol_id был равен «1» (rol: users). Все работает хорошо, когда я работаю с СУБД, но это не так, когда я работаю со Spring, потому что я получаю следующую ошибку
2018-05-01 11:00:43.432 ERROR 9448 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'rol_id' cannot be null
Мой код такой:
Роликовый стол
@Entity
@Table(name = "roles")
public class Rol implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id_rol", updatable = false, nullable = false)
private Long id;
@Column(name = "rol")
@NotEmpty
private String rolType;
@OneToMany(mappedBy= "rol")
private List<User> users = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRol() {
return rolType;
}
public void setRol(String rol) {
this.rolType = rol;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
Таблица пользователей
@Entity
@Table(name = "users")
public class User implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id_user", updatable = false, nullable = false)
private Long id;
@Column(name = "name")
@NotEmpty
@Length(min= 3, max= 25)
private String name;
@Column(name = "surname")
@NotEmpty
@Length(min= 2, max=30)
private String surname;
@Column(name = "email")
@NotEmpty
@Email
@Length(min=5, max=30)
private String email;
@Column(name = "birthdate", nullable = true)
private String birthdate;
@Column(name = "created_at")
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createdAt = new Date();
@Column(name = "gender")
@NotEmpty
@Length(min=4, max=6)
private String gender;
@Column(name = "username")
@NotEmpty
@Length(min=3, max=20)
private String username;
@Column(name = "pass")
@NotEmpty
@Length(min=8, max=30)
private String password;
@ManyToOne
@JoinColumn(name = "rol_id")
private Rol rol;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthdate() {
return birthdate;
}
public void setBirthdate(String birthdate) {
this.birthdate = birthdate;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/* MODOFIQUE ESTO ACA, NO SE SI ESTA BIEN */
public String getRol() {
return rol.getRol();
}
public void setRol(Rol rol) {
this.rol = rol;
}
}
Класс DAO
public interface IUserDAO extends CrudRepository<User, Long>{
}
Интерфейс UserService
public interface IUserService {
public List<User> findAll();
public void save(User user);
public User findOne(Long id);
}
Класс, реализующий UserService
@Service
public class UserServiceImpl implements IUserService{
@Autowired
IUserDAO userDAO;
@Override
@Transactional(readOnly = true)
public List<User> findAll() {
return userDAO.findAll();
}
@Override
@Transactional
public void save(User user) {
userDAO.save(user);
}
@Override
@Transactional(readOnly = true)
public User findOne(Long id) {
return userDAO.findOne(id);
}
}
Это мой контроллер
@Controller
@SessionAttributes("user")
public class UserController {
Constants c = new Constants();
@Autowired
IUserService userService;
@RequestMapping(value= "user/add", method = RequestMethod.GET)
public String addUser(Model model) {
User user = new User();
model.addAttribute("user", user);
model.addAttribute(c.TITLE, "Add User");
model.addAttribute(c.ADD_USER);
return "user-add";
}
@RequestMapping(value= "user/add", method = RequestMethod.POST)
public String addUser(@Valid User user, BindingResult result, Model model, RedirectAttributes ra, SessionStatus status) {
if (result.hasErrors()) {
return "redirect:/user/add";
}
try {
userService.save(user);
status.setComplete();
} catch(Exception e) {
return "redirect:/user/list";
}
return "user-add";
}
@RequestMapping(value= "user/list", method = RequestMethod.GET)
public String listUsers(Model model) {
model.addAttribute("users", userService.findAll());
model.addAttribute(c.TITLE, "Users List");
model.addAttribute(c.LIST_USER);
return "user-list";
}
}
И мой взгляд с тимелистом
<form th:action = "@{/user/add}" method = "POST" th:object = "${user}" style = "width: 70%;">
<div class = "form-group">
<label for = "inputName" class = "text-uppercase font-weight-bold">Name</label>
<input type = "text" class = "form-control" id = "inputName" th:field = "*{name}" autocomplete = "off">
</div>
<div class = "form-group">
<label for = "inputSurname" class = "text-uppercase font-weight-bold">Surname</label>
<input type = "text" class = "form-control" id = "inputSurname" th:field = "*{surname}" autocomplete = "off">
</div>
<div class = "form-group">
<label for = "inputEmail" class = "text-uppercase font-weight-bold">Email</label>
<input type = "email" class = "form-control" id = "inputEmail" th:field = "*{email}" autocomplete = "off">
</div>
<div class = "form-group">
<label for = "inputBirthdate" class = "text-uppercase font-weight-bold">Birthdate</label>
<input type = "date" class = "form-control" id = "inputBirthdate" th:field = "*{birthdate}" autocomplete = "off">
</div>
<div class = "form-group mb-5">
<label for = "inputGender" class = "text-uppercase font-weight-bold">Gender</label>
<select type = "date" class = "form-control" id = "inputGender" th:field = "*{gender}">
<option th:value = "other">Other</option>
<option th:value = "male">Male</option>
<option th:value = "female">Female</option>
</select>
</div>
<div class = "form-group">
<label for = "inputUsername" class = "text-uppercase font-weight-bold">Username</label>
<input type = "text" class = "form-control" id = "inputUsername" th:field = "*{username}" autocomplete = "off">
</div>
<div class = "form-group">
<label for = "inputPassword" class = "text-uppercase font-weight-bold">Password</label>
<input type = "password" class = "form-control" id = "inputPassword" th:field = "*{password}" autocomplete = "off">
</div>
<button type = "submit" class = "btn btn-primary w-100">
Add User
</button>
</form>
Все, что я хочу, я устанавливаю равным 1 rol_id, когда делаю вставку. Почему-то работает только в СУБД, а в Spring - нет.
Заранее спасибо.
У меня в таблице уже есть 2 роли.
Не могли бы вы показать нам, как вы пытаетесь создать User
?
@crizzis что ты имеешь в виду? Я добавил еще свой код.
У вас есть Rol DAO / Service? У каждого пользователя будет Rol с ID = 1?
Внутри UserController.save
вы просто вызываете userService.save(user)
. user.rol
вообще заселен в этот момент? Столбец rol_id
настроен так, чтобы не допускать значения NULL, что означает, что вы не можете оставить user.rol
пустым
Я не. Потому что мне не нужно сохранять / редактировать роли. Все, что мне нужно, - это установить 1 столбец rol_id в Пользователи, когда я делаю вставку
Не думаю, что понимаю. Как вы планируете заполнить rol_id
, не устанавливая для user.rol
ненулевое значение? Это JPA, вы не обрабатываете столбцы соединения и таблицы напрямую, вместо этого вы устанавливаете ассоциации между объектами
@crizzis Думаю, не заселен. В любом случае я добавил модифицированный класс Rol к этому частный Long id = (длинный) 1;, но я продолжаю получать ту же ошибку
Да, потому что вы где-нибудь создаете новый Rol, поэтому объект Rol пустой, а rol_id - null.
Не думаю, что понимаю. Как вы планируете заполнить rol_id
, не устанавливая для user.rol
ненулевое значение? Это JPA, вы не обрабатываете объединенные столбцы и таблицы напрямую, вместо этого вы устанавливаете ассоциации между объектами.
Если вы хотите, чтобы вновь созданным пользователям была назначена роль с id=1
по умолчанию, вам следует соответствующим образом изменить свою службу:
@Override
@Transactional
public void save(User user) {
user.setRol(roleDao.getOne(1l));
userDAO.save(user);
}
Я думаю, вы должны сделать это таким образом: 1: Создайте новый Rol (в пустой таблице он будет иметь ID = 1) или загрузите Rol с ID = 1. 2: Установите этот Rol для пользователя (user.setRol (rol )) и сохраните пользователя.