【问题标题】:@Column or @Basic JPA annotations ignored in spring-data-jpa schema creation在 spring-data-jpa 模式创建中忽略 @Column 或 @Basic JPA 注释
【发布时间】:2013-11-20 16:29:30
【问题描述】:

我完全被我期望开箱即用的东西弄糊涂了。所以要么我做错了什么,要么这只是一个误解。

我正在尝试在 JPA 实体类中使用 getter/setter 注释。我坚持使用在 JPA wiki 上找到的示例(s.http://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes#Conversion)。示例如下:

    @Entity
    public class Employee {
        ...
        private boolean isActive;
        ...
        @Transient
        public boolean getIsActive() {
            return isActive;
        }
        public void setIsActive(boolean isActive) {
            this.isActive = isActive;
        }
        @Basic
        private String getIsActiveValue() {
            if (isActive) {
                return "T";
            } else {
                return "F";
            }
        }
        private void setIsActiveValue(String isActive) {
            this.isActive = "T".equals(isActive);
        }
    }

我采用了我能找到的最清晰、最干净的 spring-data-jpa 示例:http://spring.io/guides/gs/accessing-data-jpa/

我从 git 中检查了它并将他们的示例实体类(s.https://github.com/spring-guides/gs-accessing-data-jpa/blob/master/complete/src/main/java/hello/Customer.java)更改为如下所示:

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String firstName;
    private String lastName;

    protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

    @Transient
    private boolean isActive;

    @Transient
    public boolean getIsActive() {
        return isActive;
    }
    public void setIsActive(boolean isActive) {
        this.isActive = isActive;
    }

    @Column
    private String getIsActiveValue() {
        if (isActive) {
            return "T";
        } else {
            return "F";
        }
    }
    private void setIsActiveValue(String isActive) {
        this.isActive = "T".equals(isActive);
    }

}

现在什么都没有改变。不会创建相应的字符串字段。创建数据库表的日志中的行仍然如下所示:

17:11:10.540 [main] DEBUG o.h.tool.hbm2ddl.SchemaUpdate - create table Customer (id bigint generated by default as identity, firstName varchar(255), lastName varchar(255), primary key (id))

我完全不知道这可能是什么原因。我找不到 spring-data-jpa 不允许对 getter 进行注释的文档。

任何帮助将非常非常感谢!

【问题讨论】:

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


    【解决方案1】:

    我认为您只是混合了注释:您必须注释字段或 getter,但不能同时注释两者。一旦决定注释 ID 字段,就必须注释所有字段(而不是 getter),反之亦然:如果注释了 getId() 方法,则必须注释所有方法。

    【讨论】:

    • 这也有助于正确编码布尔值,不要简单地使用'getIsActive'我们isActive()。这不是这里的问题,但遵守约定很重要。
    • 谢谢!不知何故,我在规格中没有看到这一点。吸气剂上的所有东西似乎都可以正常工作。
    【解决方案2】:

    如果您希望它与 '@Transient' 注释一起使用,您应该按照 Andrei 的建议进行操作,您可以为 isActiveValue 添加一个额外的字段,但最重要的是要一致地注释,否则您将获得不可预测的行为。

    当注释字段与属性(getter 和 setter)时,它会有所不同。

    在您的情况下,您似乎想在 getter 中执行一些逻辑,因此注释字段可能不会获得所需的结果。我不是特别喜欢这种逻辑,但我知道有必要对 getter 进行注释。

    考虑到您上面代码中的逻辑,我会简单地完全消除字段上的瞬态并将带有注释的逻辑放在 getter 和 setter 中。

    @Entity
    @Table(name = "Customer")
    public class Customer {
    
        private static final String IS_ACTIVE = "T";
    
        private long id;
        private String firstName;
        private String lastName;
        private String isActive = "";
    
        protected Customer() {}
    
        public Customer(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        @Column(unique = true, nullable = false)
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
        @Column(unique = true, nullable = false)
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        @Column(unique = true, nullable = false)
        public String getIsActive() {
            return isActive;
        }
    
        public void setIsActive(String isActive) {
            this.isActive = isActive;
        }
    
        @Transient
        public boolean isActive() {
            return isActive.equals(IS_ACTIVE);
        }
    
        @Override
        public String toString() {
            return String.format(
                    "Customer[id=%d, firstName='%s', lastName='%s']",
                    id, firstName, lastName);
        }
    }
    

    【讨论】:

    • 另外,为了安全起见,我应该将 isActive 编码如下 public boolean isActive() { return IS_ACTIVE.equals(isActive); } 午餐时间匆忙,没有注意那个细节。
    • 在该 ID 上添加注释,同时注释 getter 真的会搞砸,我什至测试了它。我的结论是要与规范中的规定保持一致。
    • 感谢您的示例。我必须删除那些“unique = true”注释才能运行测试。由于它们不是我面临的问题的一部分,我只是忽略了它们。没有它们,它工作正常!
    • 太棒了,回顾您的代码,您可能希望将 isActive 初始化为“F”以保持一致性。当然,它的工作原理完全相同。 - T
    猜你喜欢
    • 1970-01-01
    • 2015-04-30
    • 2015-11-13
    • 1970-01-01
    • 2014-10-06
    • 2019-07-02
    • 2017-11-17
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多