thymeleaf 和 spring-boot 丢失的复杂对象

Posted

技术标签:

【中文标题】thymeleaf 和 spring-boot 丢失的复杂对象【英文标题】:Complex object lost in from with thymeleaf and spring-boot 【发布时间】:2017-03-12 07:39:14 【问题描述】:

我有一个内部有嵌套复杂对象的对象:

public class MonitoringSystem 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String name;
    private String url;
    private String username;
    private String password;
    @Transient
    private String passwordConfirm;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name ="anonymization_id")
    private Anonymization anonymization;

当我创建一个新对象或编辑一个现有对象时,我想保留我的匿名对象。为此,我尝试将其保存在 <input type="hidden"> 中,就像我保留我的身份一样。

控制器:

@Controller
public class MonitoringSystemController 

    // some Code

    @RequestMapping("monitoringsystem/edit/id")
    public String edit(@PathVariable Long id, Model model) 
        model.addAttribute("monitoringsystem", monitoringSystemRepository.findOne(id));
        return "monitoringsystem/form";
    

    @RequestMapping("/monitoringsystem/new")
    public String newMonitoringSystem(Model model) 
        model.addAttribute("monitoringsystem", new MonitoringSystem());

        return "monitoringsystem/form";
    

    @RequestMapping(value = "/monitoringsystem/save", method = RequestMethod.POST)
    public String save(MonitoringSystem monitoringSystem) 
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = userRepository.findByUsername(auth.getName());
        long id = user.getCloudProvider().getId();

        anonymizationRepository.save(monitoringSystem.getAnonymization());

        // more code
    

表格:

<form class="form-horizontal" th:modelAttribute="monitoringsystem"
      th:object="$monitoringsystem" th:action="@/monitoringsystem/save" method="post">
  <input type="hidden" th:field="*id"/>
  <input type="hidden" th:field="*anonymization"/>
  <fieldset>
    <legend>New Monitoring-System</legend>
    <div class="form-group">
      <label class="col-md-4 control-label" for="textinput">Systemname</label>
      <div class="col-md-5">
        <input th:field="*name" class="form-control input-md" type="text"/>
      </div>
    </div>
    <div class="form-group">
      <label class="col-md-4 control-label" for="textinput">URL</label>
      <div class="col-md-5">
        <input th:field="*url" class="form-control input-md" type="text"/>
      </div>
    </div>
    <div class="form-group">
      <label class="col-md-4 control-label" for="textinput">Username</label>
      <div class="col-md-5">
        <input th:field="*username" class="form-control input-md" type="text"/>
      </div>
    </div>
    <div class="form-group">
      <label class="col-md-4 control-label" for="textinput">Password</label>
      <div class="col-md-5">
        <input th:field="*password" class="form-control input-md" type="password"/>
      </div>
    </div>
    <div class="form-group">
      <label class="col-md-4 control-label" for="textinput">Confirm Password</label>
      <div class="col-md-5">
        <input th:field="*passwordConfirm" class="form-control input-md" type="password"/>
      </div>
    </div>
    <div class="form-group">
      <label class="col-md-4 control-label" for="singlebutton"></label>
      <div class="col-md-4">
        <a th:href="@/monitoringsystem" class="btn btn-default btn-small">Cancel</a>
        <button id="singlebutton" name="singlebutton" class="btn btn-primary btn-small">
          Submit
        </button>
      </div>
    </div>
  </fieldset>
</form>

不幸的是,这不起作用。当我尝试使用monitoringSystem.getAnonymization() 在保存方法中获取匿名对象时,我得到了Nullpointerexception。所以我猜这个对象没有正确存储在隐藏字段中。如何正确传递对象,使其在创建或编辑过程中不会丢失?

【问题讨论】:

你在MonitoringSystem 构造函数中实例化Anonymization 吗?在newMonitoringSystem-Method 中,如果您没有在构造函数中创建Anonymization,则为空 是的,它在构造函数中实例化:public MonitoringSystem() this.setAnonymization(new Anonymization()); 【参考方案1】:

我现在以不同的方式解决了我的问题。我离开了这个隐藏的字段并将我的对象存储在一个会话中。在保存方法中,将它们从会话中拉出并再次将其添加到我的监视系统对象中。这可以完美运行,并且不会丢失任何数据。

此外,它更节省,因为用户可以轻松操作隐藏字段。

但感谢您的帮助。

【讨论】:

【参考方案2】:

您将整个对象绑定到该字段。应该是

<input type="hidden" th:field="*anonymization.id"/>

【讨论】:

这可行,但我必须绑定每个字段: 我的对象已传递,但没有来自对象中其他字段的所有数据,例如 anonymizeHostName 等。如果有可能传递整个对象而不关心每个字段,那就太好了.有选择吗? 您仍然可以保留您的 MonitoringSystem 对象。即使添加所有字段,Spring Data JPA 也会抱怨分离的Anonymization 对象。但这应该用CascadeType.MERGE 解决。总结一下:为隐藏字段绑定anonymization.id -> 获取monitoringSystem 实例并保存。 我测试过了。如果我只添加 id 我的对象被保存但所有其他字段都具有默认值。如果我在输入中添加 id 和所有其他字段,我的对象将按原样保存(包含所有现有数据)。顺便说一句:我的对象中已经有CascadingType.ALL

以上是关于thymeleaf 和 spring-boot 丢失的复杂对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 spring-boot 和 thymeleaf 设置标准 i18n 语言环境?

Spring-Boot + Spring-MVC + Thymeleaf + Apache Tiles

Spring-Boot 之Thymeleaf

如何将布局方言添加到spring-boot thymeleaf自动配置文件

Spring-boot(二)--thymeleaf

Thymeleaf 无法检测到 spring-boot 项目中的模板