确保Java中的UML约束?

时间:2013-06-07 13:08:16

标签: java model uml constraints

假设我的应用程序的设计有两个类:PersonCompany。还假设我定义了一个UML图,它定义了PersonCompany之间的一对多关系:每个Person对象必须只属于一个Company,并且Company可以包含许多Person s。

确保此简单约束始终成立的最佳实践是什么,即,Person对象包含在多个Company中的时间点永远不会存在?我想到了三种方法:

  1. 拥有完美的,无错误的代码,永远不会违反我的任何遗嘱。然而,作为一个现实主义者,我知道这很难或不可能,尤其是随着约束数量的增加。

  2. 实现手动检查每个约束的ensureCorrectness()方法。在此示例中,它将循环遍历所有Person,并确保只有一个Company包含Person。如果没有,它将打印错误。我会经常这种方法。

  3. 使用例如Hibernate来定义数据库模式并将数据存储到数据库中。在模式中,我可以定义一个约束来匹配我的UML图中的约束。然后,每当我将数据保存到数据库中时,Hibernate将检查所有约束并在出现问题时打印错误。

  4. 但我不禁想知道在Java中是否有另一种更清洁的方法,不依赖于(1)完美,(2)手动验证,或(3)关系数据库。是否有一个库或框架允许我在代码中指定注释类似于:

    @OneToMany(Person, Company)

    或者更具体地说:

    @OneToMany(Person, Company.persons)

    假设Company类有一个List<Person> persons成员变量。

    如果我想确保一个人的社会安全号码在所有Person中都是唯一的,我可以说:

    @Unique(Person.SSN)

    Java是否存在类似的内容?

4 个答案:

答案 0 :(得分:0)

公司与人之间的关系并不困难。制作例如包含公司中包含的Person元素的列表。您必须手动确保的一件事是列表不包含单个Person的多个实例。

另一种方式更难。您必须手动检查(每个列表不包含同一Person的多个实例)。但是你可以将它与之前的限制结合起来:

所有人员名单的长度应等于所有具有独特人士的名单的长度。

我对数据库知之甚少,但我会选择第二个选项(ensureCorrectNess)来检查上面的手册限制。

答案 1 :(得分:0)

我会在Java中实现它:

public class Company {
    Set<Person> persons;
    ...
    public void addPerson(Person person) {
        if (person.getCompany() != this) { // Avoiding an infinite loop between addPerson() and setCompany()
            person.setCompany(this);
            persons.add(person);
        }
    }
    public boolean removePerson(Person person) {
        return persons.remove(person);
    }
    ...
}

public class Person {
    Company company;
    public Person(Company company) {
        this.company = company;
    }
    public void setCompany(Company company) {
        if (this.company != null) {
            this.company.remove(this);
        }
        this.company = company;
        company.addPerson(this);
    }
    ...
}

在代码中,Person不能有多个CompanyCompany的列表为Persons。使用Person(Company)构造函数,Person至少分配了一家公司。

编辑:要修改Set(无重复项),您必须通过调用addPerson()方法的Person.setCompany()方法。此方法将从之前的Person列表中删除Company,并将其添加到新的Company列表中。

setCompany()中,您必须致电addPerson(),因为程序员可以直接将Person分配给Company,而无需先调用addPerson()。< / p>

答案 2 :(得分:0)

我会选择#1,与封装相结合。这样,必须100%无bug的代码量非常小

public class Company {
    private List<Person> persons = new ArrayList<>();
    private List<Person> publicPerson = Collections.unmodifiableList(persons);

    public List<Person> getPersons { return publicPersons; }

    public void addPerson(Person p) {
         ... ensure p is removed from old company
         p.setCompany(this);
         persons.add(p);
    }

}

public class Person {
    private Company company;
    /* pkg-private */ setCompany(Company company) {
        this.company = company;
    }
    public Company getCompany() {
        return company;
    }
}

小心,这段代码不是线程安全的!

请注意,如果保存到数据库,hibernate将仅检查约束。由于缓存,可能会出现不一致。

答案 3 :(得分:-1)

首先,您可以通过将db中的col设置为null并且客户ID唯一来轻松地在DB中配置所有这些内容。 您可以使用之前和之后的触发器来确保删除数据或将数据添加到数据库中。

第二个选项,您可以使用哈希映射来包含数据,从而在java类上设置所有数据库。

在我看来,第一种选择更容易..