Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] orm框架,主键必须命名为id,否则会出错 #108

Open
yawuaec opened this issue Jun 4, 2024 · 21 comments
Open

[BUG] orm框架,主键必须命名为id,否则会出错 #108

yawuaec opened this issue Jun 4, 2024 · 21 comments

Comments

@yawuaec
Copy link

yawuaec commented Jun 4, 2024

根本原因是 OrmContext.getAccessor().insert() 并没有把@Id注解的字段当作主键

例如主键命名为aaa

public class UserEntity implements IEntity<Long> {
    @Id
    private long aaa;

    @Override
    public Long id() {
        return aaa;
    }
}

插入数据库后会生成{_id:'xxxxxxxxxxxx',aaa=1}这样的数据

然后使用 OrmContext.getAccessor().load(1L, UserEntity.class) 查询的时候,因为_id不是1L,所以查询不到了

只有主键字段名为 id 的时候正常,这个是BUG吗,还是我使用方式错了?

@jaysunxiao
Copy link
Contributor

image

https://www.mongodb.com/docs/manual/reference/method/db.collection.insertOne/#mongodb-method-db.collection.insertOne

这个有点难办,id是mongodb的不成文规定,依赖的底层驱动并没有能修改id这个字段的方法

@jaysunxiao
Copy link
Contributor

image

就算使用底层驱动去插入,也得手动指定 _id 字段。
我这边也就只能在启动的时候做个校验,让字段名称只能是id了。

@yawuaec
Copy link
Author

yawuaec commented Jun 5, 2024

这样的话很麻烦了,每个实体类的主键都必须叫做id

比如 学生的主键是学号,教师的主键是身份证号

在代码里没法给主键命名,全部都是id,有时候实体多了不好区分每个主键的含义。

@jaysunxiao
Copy link
Contributor

确实如此,本身@id注解的含义就可以自定义名称,然后发现底层api不支持,有点违背初衷

@yawuaec
Copy link
Author

yawuaec commented Jun 5, 2024

public class UserEntity implements IEntity<Long> {

    private long id;

    @Id
    private long aaa;

    public void setAaa(long aaa) {
        this.aaa = aaa;
        this.id = aaa;
    }

    @Override
    public Long id() {
        return id;
    }
}

目前是这样解决的,还有更好的办法吗?

@jaysunxiao
Copy link
Contributor

public class UserEntity implements IEntity<Long> {

    private long id;

    @Id
    private long aaa;

    public void setAaa(long aaa) {
        this.aaa = aaa;
        this.id = aaa;
    }

    @Override
    public Long id() {
        return id;
    }
}

目前是这样解决的,还有更好的办法吗?

这样做也没有什么问题,就是多复制一个变量,问题不大

@sandogeek
Copy link
Contributor

sandogeek commented Jul 23, 2024

public class UserEntity implements IEntity<Long> {

    private long id;

    @Id
    private long aaa;

    public void setAaa(long aaa) {
        this.aaa = aaa;
        this.id = aaa;
    }

    @Override
    public Long id() {
        return id;
    }
}

目前是这样解决的,还有更好的办法吗?

这样做也没有什么问题,就是多复制一个变量,问题不大

实际上框架可以改动为将@Id标注的字段映射到_id字段,从数据库读取回来的时候也是如此,这样业务层就不用改动了

@jaysunxiao
Copy link
Contributor

public class UserEntity implements IEntity<Long> {

    private long id;

    @Id
    private long aaa;

    public void setAaa(long aaa) {
        this.aaa = aaa;
        this.id = aaa;
    }

    @Override
    public Long id() {
        return id;
    }
}

目前是这样解决的,还有更好的办法吗?

这样做也没有什么问题,就是多复制一个变量,问题不大

实际上框架可以改动为将@Id标注的字段映射到_id字段,从数据库读取回来的时候也是如此,这样业务层就不用改动了

这个会有点歧义,比如我有一个@id标注的name字段,如果强制映射到_id字段,那么数据库就找不到name这个字段了

@sandogeek
Copy link
Contributor

public class UserEntity implements IEntity<Long> {

    private long id;

    @Id
    private long aaa;

    public void setAaa(long aaa) {
        this.aaa = aaa;
        this.id = aaa;
    }

    @Override
    public Long id() {
        return id;
    }
}

目前是这样解决的,还有更好的办法吗?

这样做也没有什么问题,就是多复制一个变量,问题不大

实际上框架可以改动为将@Id标注的字段映射到_id字段,从数据库读取回来的时候也是如此,这样业务层就不用改动了

这个会有点歧义,比如我有一个@id标注的name字段,如果强制映射到_id字段,那么数据库就找不到name这个字段了

数据库没有该字段似乎也挺合理?

@sandogeek
Copy link
Contributor

sandogeek commented Jul 24, 2024

id字段自动映射到mongodb _id实际是bson.codecs带来的特性,目前bson.codecs提供了简单的办法关闭此特性。可参考此连接:MongoDB Java driver converts id field of nested object into _id
所以只需要简单修改即可实现上述映射

@jaysunxiao
Copy link
Contributor

jaysunxiao commented Jul 25, 2024

收到,等我下周有时间了来实践一下。你能改的话,也可以提pr。

@jaysunxiao
Copy link
Contributor

id字段自动映射到mongodb _id实际是bson.codecs带来的特性,目前bson.codecs提供了简单的办法关闭此特性。可参考此连接:MongoDB Java driver converts id field of nested object into _id 所以只需要简单修改即可实现上述映射

feat[orm]: id filed can use other name with @BsonId annotation

这个提交中优化了,可以不使用id作为主键名称,需要同步使用 @BsonId 这个注解

@jaysunxiao
Copy link
Contributor

jaysunxiao commented Jul 29, 2024

image

底层会做判断,非id名词的主键必须使用@BsonId这个注解,否则会报错提示

@sandogeek
Copy link
Contributor

id字段自动映射到mongodb _id实际是bson.codecs带来的特性,目前bson.codecs提供了简单的办法关闭此特性。可参考此连接:MongoDB Java driver converts id field of nested object into _id 所以只需要简单修改即可实现上述映射

feat[orm]: id filed can use other name with @BsonId annotation

这个提交中优化了,可以不使用id作为主键名称,需要同步使用 @BsonId 这个注解

这个有个值得优化的点:使用zfoo的@id和@BsonId 在不同的字段,最终会使用@BsonId 的字段作为主键。已提交了一个pr,可优化这点

@jaysunxiao
Copy link
Contributor

jaysunxiao commented Jul 30, 2024

@sandogeek 我给mongodb官方提了一个pr,如果能合进去的话直接把@id注解继承@BsonId注解就可以了。 mongo-java-driver/pull/1464

现在优先使用你的这个pr方案128 解决目前需要使用两个注解的问题

@jaysunxiao
Copy link
Contributor

jaysunxiao commented Jul 30, 2024

id字段自动映射到mongodb _id实际是bson.codecs带来的特性,目前bson.codecs提供了简单的办法关闭此特性。可参考此连接:MongoDB Java driver converts id field of nested object into _id 所以只需要简单修改即可实现上述映射

feat[orm]: id filed can use other name with @BsonId annotation
这个提交中优化了,可以不使用id作为主键名称,需要同步使用 @BsonId 这个注解

这个有个值得优化的点:使用zfoo的@id和@BsonId 在不同的字段,最终会使用@BsonId 的字段作为主键。已提交了一个pr,可优化这点

我仔细研究了一下这个Convention,和我提的这个pr mongo-java-driver/pull/1464 关系不是非常大,是不冲突的,后面即使合进去也可以继续使用你的这个pr方案128

@jaysunxiao
Copy link
Contributor

@sandogeek 另外提三点小小的优化:

  1. 注解使用instanceof Id有点奇怪,可以直接==或者equals判断,虽然最终判断正常确实不符合正常的写法
  2. IllegalStateException一般指系统环境异常换个其它的异常更好一点
  3. ZfooAnnotationConvention 去掉 Zfoo,这个大写看起来不太美观

@jaysunxiao
Copy link
Contributor

@sandogeek mongodb官方已经决定接受这个pr mongo-java-driver/pull/1464 ,后面就等版本更新,然后两者并存

@sandogeek
Copy link
Contributor

@sandogeek 另外提三点小小的优化:

  1. 注解使用instanceof Id有点奇怪,可以直接==或者equals判断,虽然最终判断正常确实不符合正常的写法
  2. IllegalStateException一般指系统环境异常换个其它的异常更好一点
  3. ZfooAnnotationConvention 去掉 Zfoo,这个大写看起来不太美观

嗯,你有空优化一波?

@jaysunxiao
Copy link
Contributor

@sandogeek 另外提三点小小的优化:

  1. 注解使用instanceof Id有点奇怪,可以直接==或者equals判断,虽然最终判断正常确实不符合正常的写法
  2. IllegalStateException一般指系统环境异常换个其它的异常更好一点
  3. ZfooAnnotationConvention 去掉 Zfoo,这个大写看起来不太美观

嗯,你有空优化一波?

这个是你提的你改吧。。。

@sandogeek
Copy link
Contributor

@sandogeek 另外提三点小小的优化:

  1. 注解使用instanceof Id有点奇怪,可以直接==或者equals判断,虽然最终判断正常确实不符合正常的写法
  2. IllegalStateException一般指系统环境异常换个其它的异常更好一点
  3. ZfooAnnotationConvention 去掉 Zfoo,这个大写看起来不太美观

嗯,你有空优化一波?

这个是你提的你改吧。。。

看起来已merge,看来得重新提pr了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants