Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 即使表单字段留空,也会提交空字符串,并在Spring中创建新实体_Java_Spring_Hibernate_Spring Data Jpa_Thymeleaf - Fatal编程技术网

Java 即使表单字段留空,也会提交空字符串,并在Spring中创建新实体

Java 即使表单字段留空,也会提交空字符串,并在Spring中创建新实体,java,spring,hibernate,spring-data-jpa,thymeleaf,Java,Spring,Hibernate,Spring Data Jpa,Thymeleaf,我有两个实体:Student和StudentDetails。学生只能有一个或没有学生详细信息。当我提交表单以保存学生时,也会保存学生详细信息。如果我发送StudentDetailsentity的数据,这没关系。但即使我没有为StudentDetails实体发送任何数据,这种情况也会发生。保存三个Students后的图像: 学生表格: 学生详细信息表格: 我希望第1,3行不会保存在student\u details表中。而在student表student\u details\u id中,这两个

我有两个实体:
Student
StudentDetails
学生
只能有一个或没有
学生详细信息
。当我提交表单以保存
学生
时,也会保存
学生详细信息
。如果我发送
StudentDetails
entity的数据,这没关系。但即使我没有为
StudentDetails
实体发送任何数据,这种情况也会发生。保存三个
Student
s后的图像:

学生
表格

学生详细信息
表格

我希望第1,3行不会保存在
student\u details
表中。而在
student
student\u details\u id
中,这两个变量的
null

我如何实现@OneToOne关系,其中父/所有者实体可以有可选的子实体(如果存在一个,如果不存在则为零)

这是我的密码:

Student.java

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_name")
    private String studentName;

    @Column(name = "student_roll")
    private String studentRoll;

    @Column(name = "student_class")
    private String studentClass;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "student_details_id")
    private StudentDetails studentDetails;

    // Constructors, Getters and Setters
}
@Entity
@Table(name = "student_details")
public class StudentDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_contact")
    private String studentContact;

    @Column(name = "student_email")
    private String studentEmail;

    @Column(name = "student_address")
    private String studentAddress;

    @OneToOne(mappedBy = "studentDetails", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
    @JsonIgnore
    private Student student;

    // Constructors, Getters and Setters
}
@Controller
@RequestMapping("/students")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    @GetMapping("/add")
    public String add(Model theModel) {
        Student theStudent = new Student();
        theModel.addAttribute("theStudent", theStudent);
        return "student/student_add_form";
    }

    @PostMapping("/create")
    public String create(@ModelAttribute("theStudent") Student theStudent) {
        theStudent.setId((long) 0);
        studentRepository.save(theStudent);
        return "redirect:/students/index";
    }
}
StudentDetails.java

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_name")
    private String studentName;

    @Column(name = "student_roll")
    private String studentRoll;

    @Column(name = "student_class")
    private String studentClass;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "student_details_id")
    private StudentDetails studentDetails;

    // Constructors, Getters and Setters
}
@Entity
@Table(name = "student_details")
public class StudentDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_contact")
    private String studentContact;

    @Column(name = "student_email")
    private String studentEmail;

    @Column(name = "student_address")
    private String studentAddress;

    @OneToOne(mappedBy = "studentDetails", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
    @JsonIgnore
    private Student student;

    // Constructors, Getters and Setters
}
@Controller
@RequestMapping("/students")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    @GetMapping("/add")
    public String add(Model theModel) {
        Student theStudent = new Student();
        theModel.addAttribute("theStudent", theStudent);
        return "student/student_add_form";
    }

    @PostMapping("/create")
    public String create(@ModelAttribute("theStudent") Student theStudent) {
        theStudent.setId((long) 0);
        studentRepository.save(theStudent);
        return "redirect:/students/index";
    }
}
StudentController.java

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_name")
    private String studentName;

    @Column(name = "student_roll")
    private String studentRoll;

    @Column(name = "student_class")
    private String studentClass;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "student_details_id")
    private StudentDetails studentDetails;

    // Constructors, Getters and Setters
}
@Entity
@Table(name = "student_details")
public class StudentDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "student_contact")
    private String studentContact;

    @Column(name = "student_email")
    private String studentEmail;

    @Column(name = "student_address")
    private String studentAddress;

    @OneToOne(mappedBy = "studentDetails", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
    @JsonIgnore
    private Student student;

    // Constructors, Getters and Setters
}
@Controller
@RequestMapping("/students")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    @GetMapping("/add")
    public String add(Model theModel) {
        Student theStudent = new Student();
        theModel.addAttribute("theStudent", theStudent);
        return "student/student_add_form";
    }

    @PostMapping("/create")
    public String create(@ModelAttribute("theStudent") Student theStudent) {
        theStudent.setId((long) 0);
        studentRepository.save(theStudent);
        return "redirect:/students/index";
    }
}
学生添加表单.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.css">
<title>Student List</title>
</head>

<body>
    <div class="container">
        <div class="row">
            <div class="col-9">
                <h1 th:text="'Add New Student'"></h1>
            </div>
            <div class="col-3">
                <a th:href="@{/students/index}" class="btn btn-success">View Student List</a>
            </div>
        </div>
        <div class="row">
            <form action="#" th:action="@{/students/create}" th:object="${theStudent}" th:method="POST" class="col-12">
                <div class="row">
                    <div class="form-group col-3">
                        <label for="studentName">Name:</label> <input type="text" class="form-control"
                            id="studentName" name="studentName" placeholder="Enter Student's Name" th:field="*{studentName}">
                    </div>
                    <div class="form-group col-3">
                        <label for="studentClass">Class:</label> <input type="text" class="form-control"
                            id="studentClass" name="studentClass" placeholder="Enter Student's Class" th:field="*{studentClass}">
                    </div>
                    <div class="form-group col-3">
                        <label for="studentRoll">Roll:</label> <input type="text" class="form-control"
                            id="studentRoll" name="studentRoll" placeholder="Enter Student's Roll" th:field="*{studentRoll}">
                    </div>
                    <div class="form-group col-3">
                        <label for="studentContact">Contact:</label> <input type="text" class="form-control"
                            id="studentContact" name="studentContact" placeholder="Enter Student's Contact"
                            th:field="*{studentDetails.studentContact}">
                    </div>
                </div>
                <div class="row">
                    <div class="form-group col-3">
                        <label for="studentEmail">Email:</label> <input type="text" class="form-control"
                            id="studentEmail" name="studentEmail" placeholder="Enter Student's Email"
                            th:field="*{studentDetails.studentEmail}">
                    </div>
                    <div class="form-group col-6">
                        <label for="studentAddress">Address:</label> <input type="text" class="form-control"
                            id="studentAddress" name="studentAddress" placeholder="Enter Student's Address"
                            th:field="*{studentDetails.studentAddress}">
                    </div>
                                        <div class="form-group col-3">
                        <label></label> <input type="submit" class="form-control btn btn-success" id="saveStudent"
                            name="saveStudent" value="Save Student">
                    </div>
                </div>
            </form>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.js"></script>
    <script>

    </script>
</body>
</html>

学生名单
姓名:
类别:
滚动:
联系人:
电邮:
地址:

您声明您没有发送任何有关StudentDetails的详细信息,但是您的表单中明确包含此数据的字段,例如:

<div class="form-group col-3">
    <label for="studentEmail">Email:</label> <input type="text" class="form-control"
        id="studentEmail" name="studentEmail" placeholder="Enter Student's Email"
        th:field="*{studentDetails.studentEmail}">
</div>

电邮:
即使表单字段留空,也会为这些值提交空字符串,因此Spring会在
Student
模型属性上绑定一个新的
StudentDetails
实例,并相应地设置绑定字段,即空字符串

为了防止这种情况,请告诉Spring将空字符串修剪为null:如果在绑定时,请求中没有与
StudentDetails
相关的非null属性,那么
StudentDetails
模型属性上的
StudentDetails
实例将不会由Spring设置

您可以全局执行此操作,也可以基于每个控制器执行此操作。例如,见:


我不确定Spring是否总是这样,即自动实例化非简单嵌套属性,但我在Boot 2.1.8(MVC 5.1.9)中进行了测试,结果就是这样。

列“student\u id”不能为null
是一个数据库约束。您需要更改列以允许空值。对于可选关系,在
@OneToOne
中使用
optional=true
,在whcih表中不清楚您看到的错误。可能是
Student.studentId
可能是
StudentDetails.Student
。它来自哪一张桌子?还有我经常遇到的问题是
cascade=CascadeType。所有的
都是持久化一个新实体。我认为应该首先保存
StudentDetails
,但是
Student
尚未保存。虽然您的问题不清楚,但您是否检查了
StudentDetails
是否设置了
Student
?您发送的请求是什么?正在保存的学生是否有学生详细信息记录?如果是这样,那是因为您没有设置关系的反面。i、 e.StudentDetails没有学生集。在双向关系中,您有责任确保内存模型的两侧设置正确。保存SudentDetails记录的唯一方法是为学生创建一条记录。你说你没有,但你一定弄错了。您发送的请求是什么,因为Student.studentDetails!=保存时为空。