Spring Data MongoDB - 使用自定义Id字段时,注释@CreatedDate不起作用

时间:2017-11-01 12:20:30

标签: java mongodb spring-boot spring-data-jpa spring-data-mongodb

我有一个简单的Persistable Class:

[assembly: ExportRenderer(typeof(ListView2), typeof(ListView2Renderer))]
namespace MyProject.iOS
{
    public partial class ListView2Renderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);
            if (Control != null && e != null)
            {
                //oldDelegate = (UITableViewSource)Control.Delegate;
                Control.Delegate = new ListView2Delegate(e.NewElement);
            }
        }
    }


    class ListView2Delegate : UITableViewDelegate
    {
        private ListView _listView;

        internal ListView2Delegate(ListView listView)
        {
            _listView = listView;
        }

        public override void WillDisplay(UITableView tableView, UITableViewCell cell, Foundation.NSIndexPath indexPath)
        {
            cell.SelectedBackgroundView = new UIView()
            {
                BackgroundColor = Color.Red.ToUIColor()
            };
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _listView = null;
            }
            base.Dispose(disposing);
        }
    }
}

一个简单的存储库:

public class Profile implements Persistable<String>{

    @Id
    private String username;

    @CreatedDate
    public Date createdDate;

    public Profile(String username) {
        this.username = username;
    }

    @Override
    public String getId() {
        return username;
    }

    @Override
    public boolean isNew() {
        return username == null;
    }
}

我的Spring Boot Application类也注明了@EnableMongoAuditing。但是我仍然无法获得注释@CreatedDate的工作。

ProfileRepository.save(新的配置文件(&#34; user1&#34;))写入没有字段createdDate的实体。我做错了什么?

编辑:这是我的Application类(没有@EnableMongoRepositories,但它可以工作,因为存储库在子包中我猜)

public interface ProfileRepository extends MongoRepository<Profile, String> {

}

编辑:添加注释EnableMongoRepositories也没有改变任何内容。

6 个答案:

答案 0 :(得分:2)

我自己遇到了这个问题,因为你自己创建了这个问题。

public Profile(String username) {
        this.username = username;
    }

通过这样做,mongo认为它不是一个新对象,并且不使用@CreatedDate注释。您还应该使用@Document注释而不是实现Persistable Class,如下所示:

@Document
public class Profile{}

答案 1 :(得分:1)

如果那是你真正的班级(Profile),那么你无法用标准工具做任何事情。

您的isNew方法将始终返回false,因为您自己设置了用户名,而当Profile即将被Spring保存时,它会检查isNew和你可能已经设置了username@LastModifiedDate适用于您的情况,但@CreatedDate不会。

如果你没有其他字段可以在isNew方法中使用,那么你必须手动设置createdDate的值(或者可能有某种拦截器可以包装所有mongo模板方法,但我不会这样做。)

例如,检查DB中是否已存在具有给定用户名的配置文件,如果是这样,只需获取它的createdDate(您可以在此处使用投影)并设置为您要保存的配置文件。否则将createdDate设置为新日期。

答案 2 :(得分:1)

您只需将@Version字段添加到@Document类中,并启用@EnableMongoAuditing。看起来像这样:

@Document
public class Profile implements Persistable<String>{

    @Vesrion
    private Long version;

    @Id
    private String username;

    @CreatedDate
    public Date createdDate;

    public Profile(String username) {
        this.username = username;
    }

    @Override
    public String getId() {
        return username;
    }

    @Override
    public boolean isNew() {
        return username == null;
    }
}

这是一个相关的问题:https://jira.spring.io/browse/DATAMONGO-946

答案 3 :(得分:1)

如 Spring Data MongoDB 问题 DATAMONGO-946 中所述,创建日期功能使用 isNew() 方法来确定是否应设置创建日期,因为实体是新的。在您的情况下,您的 isNew 方法始终返回 false,因为始终设置 username

问题中的评论为这个问题提供了两种可能的解决方案。

Persistable 解决方案

第一个选项是修复 isNew 策略,以便它正确注册新对象。评论中建议的一种方法是更改​​实现以检查 createdDate 字段本身,因为它应该只在非新对象上设置。

@Override
public boolean isNew() {
    return createdDate == null;
}

持久化实体解决方案

第二个选项是从实现 Persistable 改为使用持久化实体,并使用 @Version 注释在持久化 MongoDB 实体中注入 version 属性。请注意,这改变数据的持久化方式,因为它会向数据添加一个自动递增的 version 字段。

import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class Profile {
    @Id
    private String username;

    @CreatedDate
    public Date createdDate;

    @Version
    public Integer version;

    public Profile(String username) {
        this.username = username;
    }
}

答案 4 :(得分:0)

对我来说,我只是这样做:

    @CreatedDate
    @Field("created_date")
    @JsonIgnore
    private Instant createdDate = Instant.now();

并确保“获取/设置”可用。 希望有帮助

答案 5 :(得分:0)

我有一个类似的情况,有时我需要手动设置ID,并且确实没有办法事先知道ID是一个新的ID还是一个更新,而无需事先搜索数据库。我还知道,在实体的整个生命周期中,我将多次更新我的实体,但是只创建一次。因此,为了避免额外的数据库操作,我采用了以下解决方案:

80
80
80
80

这是利用了我在Profile上也有一个public class Regex { static boolean range(int timeval,int min,int max) { boolean status=false; if(timeval>=min && timeval<max) {status=true;} return status; } public static void main(String[] args) { String regex = "[0-9]{1,2}"; String input ="23:59:59"; String msg="please enter valid time "; String[] inputString = input.split(":"); if(inputString[0].matches(regex) && inputString[1].matches(regex) && inputString[2].matches(regex) ) { if(Regex.range(Integer.parseInt(inputString[0]), 00, 24) &&Regex.range(Integer.parseInt(inputString[1]), 00, 60) && Regex.range(Integer.parseInt(inputString[2]), 00, 60)) {msg="converted time = " + Integer.parseInt(inputString[0]) + " : " +Integer.parseInt(inputString[1])+ " : " +Integer.parseInt(inputString[2]) ;} } System.out.println(msg); } } 字段的事实,保存实体时该字段总是由spring数据更新。