Java Ebean:如何为没有属性的getter创建列

Java Ebean:如何为没有属性的getter创建列,java,playframework,ebean,playframework-2.4,Java,Playframework,Ebean,Playframework 2.4,我不想在数据库中存储来自Java的计算值 例如,我可能有一个Person类,它有一个firstName和一个lastName。我可能需要一个getter,它返回人名的总长度,而不是实际的属性 @Entity public class Person extends Model { @Id public Long id; public String firstName; public String lastName; public Int getName

我不想在数据库中存储来自Java的计算值

例如,我可能有一个Person类,它有一个
firstName
和一个
lastName
。我可能需要一个getter,它返回
人名的总长度,而不是实际的属性

@Entity
public class Person extends Model {
    @Id
    public Long id;

    public String firstName;

    public String lastName;

    public Int getNameLength() {
        return firstName.length() + lastName.length();
    }

    public Person (String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
因此,如果我创建一个新的
,如下所示:

Person bob = new Person("Bob", "Roy");
bob.save();
那么我们应该在表中列出以下内容:

|  id  |  first_name  |  last_name  |  name_length |
====================================================
|  1   |    "Bob"     |    "Roy"    |      6       |

有人知道这是否可行吗?

为了安全起见,请不要这样做

这样做会完全搞乱你的数据库。你迟早会遇到问题的。看看你的个人资料,你获得了CS学位,所以你肯定有数据库课程。请记住和,以及如果您具有依赖于其他属性的属性,您将如何打破这一点

您应该做的是创建一个瞬态字段(标记为
@transient
),或者您可以使用getter并从中提供信息。每次需要访问
name\u length
时,都会调用此getter,但不会将信息存储在数据库中

即使您想计算应用程序之外的长度,您仍然可以为此使用一些数据库函数-


根据OP提到的要求进行编辑:

在JPA中,有两种方法可以声明列——要么在字段上,要么在方法(getter/setter)上。它是这样的:

@Column(name = "complex_calculation") // Due to some bad requirement
public Integer getNameLength() {
    return fisrtName.length() + lastName.length();
}
@Entity
public class Person extends Model {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    private Integer nameLength;

    public Long getId() {
        return id;
    }

    // getter for first name and last name with @Column annotation

    @Column(name = "complex_calculation")
    public Integer getNameLength() {
        return firstName.length() + lastName.length();
    }

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

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        updateComplexCalculation();
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        updateComplexCalculation();
    }

    private void updateComplexCalculation() {
        this.nameLength = firstName.length() + lastName.length();
    }
}
但是,您在问题中提到了Ebean,并且Ebean不被视为参考JPA实现。这很可能还不受支持,但您可以在您的具体案例中尝试

还有一种方法被证明是有效的。您可以这样定义模型:

@Column(name = "complex_calculation") // Due to some bad requirement
public Integer getNameLength() {
    return fisrtName.length() + lastName.length();
}
@Entity
public class Person extends Model {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    private Integer nameLength;

    public Long getId() {
        return id;
    }

    // getter for first name and last name with @Column annotation

    @Column(name = "complex_calculation")
    public Integer getNameLength() {
        return firstName.length() + lastName.length();
    }

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

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        updateComplexCalculation();
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        updateComplexCalculation();
    }

    private void updateComplexCalculation() {
        this.nameLength = firstName.length() + lastName.length();
    }
}
重要的部分是
updateComplexCalculation
方法。在调用构造函数时,以及在每次setter调用时,您都会调用此方法来更新复杂属性。当然,您应该只在计算所需的setter调用上调用它

以下代码:

Person p = new Person("foo", "bar");
p.save();

Logger.debug("Complex calculation: " + p.getNameLength());

p.setFirstName("somethingElse");
p.save();

Logger.debug("Complex calculation: " + p.getNameLength());
那么:

[debug] application - Complex calculation: 6
[debug] application - Complex calculation: 16

为了安全起见,请不要这样做

这样做会完全搞乱你的数据库。你迟早会遇到问题的。看看你的个人资料,你获得了CS学位,所以你肯定有数据库课程。请记住和,以及如果您具有依赖于其他属性的属性,您将如何打破这一点

您应该做的是创建一个瞬态字段(标记为
@transient
),或者您可以使用getter并从中提供信息。每次需要访问
name\u length
时,都会调用此getter,但不会将信息存储在数据库中

即使您想计算应用程序之外的长度,您仍然可以为此使用一些数据库函数-


根据OP提到的要求进行编辑:

在JPA中,有两种方法可以声明列——要么在字段上,要么在方法(getter/setter)上。它是这样的:

@Column(name = "complex_calculation") // Due to some bad requirement
public Integer getNameLength() {
    return fisrtName.length() + lastName.length();
}
@Entity
public class Person extends Model {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    private Integer nameLength;

    public Long getId() {
        return id;
    }

    // getter for first name and last name with @Column annotation

    @Column(name = "complex_calculation")
    public Integer getNameLength() {
        return firstName.length() + lastName.length();
    }

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

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        updateComplexCalculation();
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        updateComplexCalculation();
    }

    private void updateComplexCalculation() {
        this.nameLength = firstName.length() + lastName.length();
    }
}
但是,您在问题中提到了Ebean,并且Ebean不被视为参考JPA实现。这很可能还不受支持,但您可以在您的具体案例中尝试

还有一种方法被证明是有效的。您可以这样定义模型:

@Column(name = "complex_calculation") // Due to some bad requirement
public Integer getNameLength() {
    return fisrtName.length() + lastName.length();
}
@Entity
public class Person extends Model {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    private Integer nameLength;

    public Long getId() {
        return id;
    }

    // getter for first name and last name with @Column annotation

    @Column(name = "complex_calculation")
    public Integer getNameLength() {
        return firstName.length() + lastName.length();
    }

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

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        updateComplexCalculation();
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        updateComplexCalculation();
    }

    private void updateComplexCalculation() {
        this.nameLength = firstName.length() + lastName.length();
    }
}
重要的部分是
updateComplexCalculation
方法。在调用构造函数时,以及在每次setter调用时,您都会调用此方法来更新复杂属性。当然,您应该只在计算所需的setter调用上调用它

以下代码:

Person p = new Person("foo", "bar");
p.save();

Logger.debug("Complex calculation: " + p.getNameLength());

p.setFirstName("somethingElse");
p.save();

Logger.debug("Complex calculation: " + p.getNameLength());
那么:

[debug] application - Complex calculation: 6
[debug] application - Complex calculation: 16

模型中的属性有什么问题?只需将其设置为
private
添加
public
getter而不添加setter,最后覆盖
save
update
方法

private Integer nameLength;

// BTW shouldn't you also count the space between first and last name?
public Integer getNameLength() {
    return firstName.length() + lastName.length();
}

@Override
public void save() {
    nameLength = firstName.length() + lastName.length();
    super.save();
}

@Override
public void update() {
    nameLength = firstName.length() + lastName.length();
    super.update();
}


如果仍要避免模型中的属性,则需要使用自定义SQL查询(可能也在重写的
save/update
方法中),如所示,或者请注意,每个保存或更新操作将至少执行2个SQL查询。

模型中的属性有什么问题?只需将其设置为
private
添加
public
getter而不添加setter,最后覆盖
save
update
方法

private Integer nameLength;

// BTW shouldn't you also count the space between first and last name?
public Integer getNameLength() {
    return firstName.length() + lastName.length();
}

@Override
public void save() {
    nameLength = firstName.length() + lastName.length();
    super.save();
}

@Override
public void update() {
    nameLength = firstName.length() + lastName.length();
    super.update();
}


如果仍要避免模型中的属性,则需要使用自定义SQL查询(可能也在重写的
save/update
方法中),如show或,注意每个save或update操作将至少执行2个SQL查询。

感谢Anton和biesior给了我一些想法

我们没有覆盖
save
update
方法,而是选择了一个私有变量,当它所依赖的变量被更新时,该变量将被重新计算

public class Person {
    @Id
    public Long id;
    private String firstName;
    private String lastName;
    private Integer nameLength;

    public String getFirstName() { 
        return firstName; 
    }

    public String getLastName() { 
        return lastName; 
    }

    public void setFirstName() {
        this.firstName = firstName;
        calculateNameLength();
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        calculateNameLength();
    }

    private void calculateNameLength() {
        nameLength = getFirstName().length + getLastName().length;
    }

}
save
update
方法中建议的更新值的方法相比,这有几个好处

private Integer nameLength;

// BTW shouldn't you also count the space between first and last name?
public Integer getNameLength() {
    return firstName.length() + lastName.length();
}

@Override
public void save() {
    nameLength = firstName.length() + lastName.length();
    super.save();
}

@Override
public void update() {
    nameLength = firstName.length() + lastName.length();
    super.update();
}
save
update
方法中重新计算意味着每次在对象上设置字段时都需要调用其中一个方法。否则,
nameLength
将不同步。例如,如果不先将对象持久化到数据库中,我无法更改Persons
firstName
,然后使用
nameLength
执行其他操作


此外,使用
save
/
update
方法将对象状态耦合到Ebean。ORM用于持久化对象状态,而不是设置对象状态。

感谢Anton和biesior给了我一些想法

我们没有覆盖
save
update
方法,而是选择了一个私有变量,当它所依赖的变量是upd时,会重新计算该变量