确保Java中的UML约束?

确保Java中的UML约束?,java,model,uml,constraints,Java,Model,Uml,Constraints,假设我的应用程序设计为两类:Person和Company。还假设我定义了一个UML图,它定义了人和公司之间的一对多关系:每个人对象必须只属于一个公司,而公司可以包含许多人 有哪些最佳实践可以确保这一简单约束始终有效,即不存在一个时间点,即一个人对象包含在多个公司中?我想到了三种方法: 拥有完美、无bug的代码,永远不会违反我的任何约束。然而,作为一个现实主义者,我知道这是困难的或不可能的,特别是随着限制的数量增加 执行手动检查每个约束的ensureCorrectness()方法。在本例中,它将遍

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

有哪些最佳实践可以确保这一简单约束始终有效,即不存在一个时间点,即一个
对象包含在多个
公司
中?我想到了三种方法:

  • 拥有完美、无bug的代码,永远不会违反我的任何约束。然而,作为一个现实主义者,我知道这是困难的或不可能的,特别是随着限制的数量增加

  • 执行手动检查每个约束的
    ensureCorrectness()
    方法。在本例中,它将遍历所有
    人员
    并确保只有一家
    公司
    包含该
    人员
    。否则,它将打印一个错误。我会经常调用这个方法

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

  • 但我不禁想知道,在Java中是否还有另一种更干净的方法可以做到这一点,它不依赖于(1)完善,(2)手动验证,或(3)关系数据库。是否有一个库或框架允许我在代码中指定注释,类似于:

    
    @一家公司(个人、公司)
    

    或者更具体地说:

    
    @OneToMany(个人、公司、个人)
    

    假设
    公司
    类有一个
    列表人员
    成员变量

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

    
    @唯一(Person.SSN)
    


    Java是否存在类似的功能?

    首先,您可以通过将DB中的col设置为非空和客户id设置为唯一,在DB中轻松配置所有这些功能。 您可以在之前和之后使用触发器,以确保数据被删除或添加到数据库中

    第二个选项,您可以使用散列映射来包含数据,从而设置java类上的所有DB


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

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

    另一种方法则更为困难。您必须手动检查(每个列表不包含同一个人的多个实例)。但您可以将其与前面的限制结合使用:

    所有人员名单的长度应等于具有唯一人员的所有名单的长度


    我对数据库了解不多,但我会选择第二个选项(EnsureRecorrectness)来检查上面的手动压缩。

    我会在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.getCompany()!=this){//避免addPerson()和setCompany()之间的无限循环
    个人、公司(本公司);
    人。添加(人);
    }
    }
    公共布尔removePerson(Person){
    返回人员。移除(人员);
    }
    ...
    }
    公共阶层人士{
    公司;
    公众人士(公司){
    这个公司=公司;
    }
    上市公司(公司){
    如果(this.company!=null){
    本公司,移除(本公司);
    }
    这个公司=公司;
    公司。addPerson(本公司);
    }
    ...
    }
    
    在代码中,
    人员
    不能有多个
    公司
    ,并且
    公司
    有一个
    人员
    列表。使用
    Person(Company)
    构造函数,
    Person
    至少分配了一个公司

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

    setCompany()
    中,您必须调用
    addPerson()
    ,因为程序员可以直接将
    Person
    分配给
    公司
    ,而无需首先调用
    addPerson()

    ,结合封装,我会选择#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;
        }
    }
    
    上市公司{
    私人列表人员=新的ArrayList();
    private List publicPerson=集合。不可修改列表(个人);
    公共列表getPersons{return publicPersons;}
    公众人士(p人){
    …确保从旧公司中删除p
    p、 赛特公司(本公司);
    增加(p);
    }
    }
    公共阶层人士{
    私营公司;
    /*私人包装*/setCompany(公司){
    这个公司=公司;
    }
    上市公司{
    返回公司;
    }
    }
    
    小心,此代码不是线程安全的


    请注意,hibernate仅在保存到数据库时检查约束。由于缓存的原因,可能会出现不一致。

    但是如何阻止
    人员
    对象出现在两个
    公司
    人员
    列表中?所以基本上你是说没有这样的f