我在CRUD应用程序中使用MySQL,Hibernate和Spring MVC。我有两个实体一对一的单向关系。当我删除用户时,地址仍在数据库中。用户和地址已正确添加。怎么了?我检查了所有堆栈上的主题,但没有找到失败的原因...以下是我的Java代码和SQL脚本。
User.java
@Table
@Entity(name = "User")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", address=" + address + "]";
}
}
Address.java
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "street")
private String street;
@Column(name = "city")
private String city;
@Column(name = "zip_code")
private String zipCode;
public Address() {
}
public Address(String street, String city, String zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
@Override
public String toString() {
return "Address [id=" + id + ", street=" + street + ", city=" + city + ", zipCode=" + zipCode + "]";
}
}
GenericService.java
public interface GenericService<T> {
List<T> getAll();
void save(T t);
User getOne(int id);
void delete(int id);
}
UserService.java
@Service
public class UserService implements GenericService<User> {
@Autowired
private UserDAO userDao;
@Override
@Transactional
public List<User> getAll() {
return userDao.getAll();
}
@Override
@Transactional
public void save(User user) {
userDao.save(user);
}
@Override
@Transactional
public User getOne(int id) {
return userDao.getOne(id);
}
@Override
@Transactional
public void delete(int id) {
userDao.delete(id);
}
}
AbstractDAO.java
public abstract class AbstractDAO<T> {
@Autowired
public SessionFactory sessionFactory;
protected Class<T> entityClass;
public AbstractDAO() {
ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass();
entityClass = (Class<T>) pt.getActualTypeArguments()[0];
}
public T getOne(int id) {
Session session = sessionFactory.getCurrentSession();
T t = session.get(entityClass, id);
return t;
}
public List<T> getAll() {
Session session = sessionFactory.getCurrentSession();
TypedQuery<T> query = session.createQuery("from " + entityClass.getSimpleName(), entityClass);
List<T> t = query.getResultList();
return t;
}
public T save(T t) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(t);
return t;
}
public void delete(int id) {
Session session = sessionFactory.getCurrentSession();
TypedQuery<T> query = session.createQuery("delete from " + entityClass.getSimpleName() + " where id=:id");
query.setParameter("id", id);
query.executeUpdate();
}
}
UserDAO.java
@Repository
public class UserDAO extends AbstractDAO<User>{
@Autowired
private SessionFactory sessionFactory;
public List<User> getAll(){
Session session = sessionFactory.getCurrentSession();
TypedQuery<User> query = session.createQuery("from "+entityClass.getSimpleName(),entityClass);
List<User> userList = query.getResultList();
return userList;
}
public User save(User user) {
Session currentSession = sessionFactory.getCurrentSession();
currentSession.saveOrUpdate(user);
return user;
}
public void delete(int id) {
Session session = sessionFactory.getCurrentSession();
TypedQuery<User> query = session.createQuery("delete from "+ entityClass.getSimpleName()+" where id=:id");
query.setParameter("id",id);
query.executeUpdate();
}
}
UserController.java
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
StringTrimmerEditor stringTrimmerEdition = new StringTrimmerEditor(true);
dataBinder.registerCustomEditor(String.class, stringTrimmerEdition);
}
@GetMapping("/list")
public String userList(Model theModel) {
List<User> theUsers = userService.getAll();
theModel.addAttribute("users", theUsers);
return "list-users";
}
@GetMapping("/showFormForAdd")
public String showFormForAdd(Model theModel) {
User theUser = new User();
theModel.addAttribute("user", theUser);
return "user-form";
}
@PostMapping("/saveUser")
public String saveUser(@ModelAttribute("user") User theUser, BindingResult bindingResult) {
userService.save(theUser);
return "redirect:/user/list";
}
@GetMapping("/showFormForUpdate")
public String showFormForUpdate(@RequestParam("userId") int theId, Model theModel) {
User user = userService.getOne(theId);
theModel.addAttribute("user", user);
return "user-form";
}
@GetMapping("/delete")
public String deleteUser(@RequestParam("userId") int theId) {
userService.delete(theId);
return "redirect:/user/list";
}
}
list-form.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<title>SimpleCRUD</title>
</head>
<body>
<nav class="navbar navbar-dark bg-primary" style="color: white">
<h3>
<i>SimpleCRUD</i>
<h3>
</nav>
<div class="container-fluid text-center">
<div class="row">
<div class="col-md-12">
<br>
<h3>
<i>Lista użytkowników</i>
</h3>
<br>
<table class="table table-sm text-center">
<thead>
<tr>
<th>Imię</th>
<th>Nazwisko</th>
<th>Ulica</th>
<th>Miasto</th>
<th>Kod pocztowy</th>
<th></th>
</tr>
</thead>
<tbody>
<c:forEach var="tempUser" items="${users}">
<c:url var="updateLink" value="/user/showFormForUpdate">
<c:param name="userId" value="${tempUser.id}" />
</c:url>
<c:url var="deleteLink" value="/user/delete">
<c:param name="userId" value="${tempUser.id}" />
</c:url>
<tr>
<td>${tempUser.firstName}</td>
<td>${tempUser.lastName}</td>
<td>${tempUser.address.street}</td>
<td>${tempUser.address.city}</td>
<td>${tempUser.address.zipCode}</td>
<td><a href="${updateLink}">Aktualizuj</a> | <a
href="${deleteLink}"
onclick="if(!(confirm('Usunąć użytkownika z bazy?'))) return false">Usuń</a></td>
</tr>
</c:forEach>
</tbody>
<p><i>Liczba użytkowników: ${fn:length(users)}</p>
</table>
<button type="button" class="btn btn-primary"
onclick="window.location.href='showFormForAdd'; return false;">Dodaj
użytkownika</button>
</div>
</div>
</div>
<footer>
<br>
<hr>
<center>
<i>SimpleCRUD 2018</i>
</center>
</footer>
</body>
</html>
user-form.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<title>SimpleCRUD</title>
</head>
<body>
<nav class="navbar navbar-dark bg-primary" style="color: white">
<h3>
<i>SimpleCRUD</i>
<h3>
</nav>
<div class="container">
<div class="row">
<div class="col-md-4">
<br>
<h3>
<i>Dodaj użytkownika</i>
</h3>
<br>
<form:form action="saveUser" modelAttribute="user" method="POST">
<form:hidden path="id" />
<form:hidden path="address.id" />
<div class="form-group">
<label>Imię: </label>
<form:input class="form-control" path="firstName" />
<form:errors path="firstName"/>
</div>
<div class="form-group">
<label>Nazwisko: </label>
<form:input class="form-control" path="lastName" />
<form:errors path="lastName"/>
</div>
<div class="form-group">
<label>Ulica: </label>
<form:input class="form-control" path="address.street" />
<form:errors path="address.street"/>
</div>
<div class="form-group">
<label>Miasto: </label>
<form:input class="form-control" path="address.city" />
<form:errors path="address.city"/>
</div>
<div class="form-group">
<label>Kod pocztowy: </label>
<form:input class="form-control" path="address.zipCode" />
<form:errors path="address.zipCode"/>
</div>
<input type="submit" class="btn btn-success" value="Zapisz" />
<a class="btn btn-primary"
href="${pageContext.request.contextPath}/user/list">Powrót do
listy</a>
</form:form>
</div>
</div>
</div>
</body>
</html>
SQL脚本
create table address (
id int(11) not null auto_increment,
street varchar(45) default null,
city varchar(45) default null,
zip_code varchar(45) default null,
primary key (id)
);
create table user (
id int(11) not null auto_increment,
first_name varchar(45) default null,
last_name varchar(45) default null,
address_id int(11) default null,
primary key (id),
KEY FK_ADDRESS_idx (address_id),
constraint FK_ADDRESS foreign key (address_id)
references address (id)
);
将用户和地址保存到数据库后,控制台发出的信息:
Hibernate: insert into address (city, street, zip_code) values (?, ?, ?)
Hibernate: insert into User (address_id, first_name, last_name) values (?, ?, ?)
删除用户和地址后从控制台获取的信息?来自数据库:
Hibernate: delete from User where id=?
从表格中删除用户后,没有如上所述的有关删除地址的信息。
答案 0 :(得分:1)
使
User
和Address
表是双向的。在Address.java中,使用getter / setter添加以下属性
@OneToOne(mappedBy="address") // variable name of join property Address in User.java private Address address;
当万一我们无法更改Address.java时,可以使用以下方法 移除孤儿。
在User.java中
@OneToOne(cascade = CascadeType.ALL, orphanRemoval=true) @JoinColumn(name = "address_id") private Address address;
答案 1 :(得分:1)
如果要在删除用户数据时也删除地址值,则首先不使用查询,而是需要基于userId获取用户对象,然后删除该对象,
因此,您删除用户的代码应如下所示:
public void delete(int id) {
User user = getOne(id); // method present in Abstract Dao class to find the object based on Id
Session session = sessionFactory.getCurrentSession();
session.delete(user);
}