java - 指定字段对于 MongoDB 是 transient 的,但对于 RestContro

我正在使用 spring-boot 来提供与 MongoDB 保持一致的 REST 接口(interface)。我正在使用“标准”依赖项为其提供动力,包括 spring-boot-starter-data-mongodbspring-boot-starter-web

但是,在我的某些类中,我有一些字段,我对 @Transient 进行了注释,这样 MongoDB 就不会保留该信息。但是,我确实希望在我的休息服务中发送此信息。不幸的是,MongoDB 和其余 Controller 似乎都共享该注释。因此,当我的前端收到 JSON 对象时,这些字段不会被实例化(但仍会被声明)。删除注释允许字段通过 JSON 对象。

如何分别为 MongoDB 和 REST 配置 transient ?

这是我的课

package com.clashalytics.domain.building;

import com.clashalytics.domain.building.constants.BuildingConstants;
import com.clashalytics.domain.building.constants.BuildingType;
import com.google.common.base.Objects;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;

import java.util.*;

public class Building {

    @Id
    private int id;

    private BuildingType buildingType;
    private int level;
    private Location location;
    // TODO http://stackoverflow.com/questions/30970717/specify-field-is-transient-for-mongodb-but-not-for-restcontroller
    @Transient
    private int hp;
    @Transient
    private BuildingDefense defenses;

    private static Map<Building,Building> buildings = new HashMap<>();

    public Building(){}
    public Building(BuildingType buildingType, int level){
        this.buildingType = buildingType;
        this.level = level;
        if(BuildingConstants.hpMap.containsKey(buildingType))
            this.hp = BuildingConstants.hpMap.get(buildingType).get(level - 1);

        this.defenses = BuildingDefense.get(buildingType, level);
    }

    public static Building get(BuildingType townHall, int level) {
        Building newCandidate = new Building(townHall,level);
        if (buildings.containsKey(newCandidate)){
            return buildings.get(newCandidate);
        }
        buildings.put(newCandidate,newCandidate);
        return newCandidate;
    }

    public int getId() {
        return id;
    }

    public String getName(){
        return buildingType.getName();
    }

    public BuildingType getBuildingType() {
        return buildingType;
    }

    public int getHp() {
        return hp;
    }

    public int getLevel() {
        return level;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public BuildingDefense getDefenses() {
        return defenses;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Building building = (Building) o;
        return Objects.equal(id, building.id) &&
                Objects.equal(hp, building.hp) &&
                Objects.equal(level, building.level) &&
                Objects.equal(buildingType, building.buildingType) &&
                Objects.equal(defenses, building.defenses) &&
                Objects.equal(location, building.location);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id, buildingType, hp, level, defenses, location);
    }
}

按原样,hpdefenses 分别显示为 0null。如果我删除 @Transient 标记,它就会通过。

最佳答案

只要您使用 org.springframework.data.annotation.Transient 它应该可以按预期工作。 Jackson 对 spring-data 一无所知,它忽略了它的注释。

有效的示例代码:

interface PersonRepository extends CrudRepository<Person, String> {}
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
class Person {
    @Id
    private String id;
    private String name;
    @Transient
    private Integer age;

    // setters & getters & toString()
}
@RestController
@RequestMapping("/person")
class PersonController {
    private static final Logger LOG = LoggerFactory.getLogger(PersonController.class);
    private final PersonRepository personRepository;

    @Autowired
    PersonController(PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    @RequestMapping(method = RequestMethod.POST)
    public void post(@RequestBody Person person) {
        // logging to show that json deserialization works
        LOG.info("Saving person: {}", person);
        personRepository.save(person);
    }

    @RequestMapping(method = RequestMethod.GET)
    public Iterable<Person> list() {
        Iterable<Person> list = personRepository.findAll();
        // setting age to show that json serialization works
        list.forEach(foobar -> foobar.setAge(18));

        return list;
    }
}

执行POST http://localhost:8080/person:

{
    "name":"John Doe",
    "age": 40
}
  • 日志输出保存人:Person{age=40, id='null', name='John Doe'}
  • person 集合中的条目: { "_id": ObjectId("55886dae5ca42c52f22a9af3"), "_class": "demo.Person", "name": "John Doe"} - 年龄不持久

执行GET http://localhost:8080/person:

  • 结果:[{"id":"55886dae5ca42c52f22a9af3","name":"John Doe","age":18}]

关于java - 指定字段对于 MongoDB 是 transient 的,但对于 RestController 不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30970717/

相关文章:

javascript - MongoError : cannot change _id of a d

mongodb - Spark 流 : foreachRDD update my mongo RDD

mongodb - MongoDB批量FindAndModify的解决方案

node.js - 聊天项目 - 使用 socket.io 进行负载平衡

mongodb - 更新 mongodb 中的嵌套文档

mongodb - 当父字段未知时,在嵌套文档中查找具有字段的记录

javascript - Mongoose 连接到 MongoDB Atlas 的最佳池大小是多少?

node.js - Mongoose,查找,返回特定属性

node.js - 将数据插入 MongoDB - 没有错误,没有插入

performance - 字段类型在 MongoDB 索引中是否重要?