从表中一对一删除关联休眠

时间:2018-08-26 11:55:44

标签: java mysql hibernate spring-mvc

我在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)
);

@EDIT

将用户和地址保存到数据库后,控制台发出的信息:

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=?

从表格中删除用户后,没有如上所述的有关删除地址的信息。

2 个答案:

答案 0 :(得分:1)

  

使UserAddress表是双向的。

     

在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);
    }