Domain Objects

Overview

Domain objects are generated from the local database schema. This means domain objects always match the schema, much like the Rails/Fowler ActiveRecord pattern.

Joist uses the Generation Gap pattern to separate boilerplate getters/setters from business logic in a separate base class that you never have to look at.

So, for each table foo, there are two files: Foo.java and FooCodegen.java. Foo.java is never touched again, so you can add domain logic without fear of it being overwritten, where as FooCodegen.java is overwritten with the latest schema information.

Example

For a table child, you work with Child.java, which is a clean-slate so you can focus solely on the business logic:

    public class Child extends ChildCodegen {
    }

While the base class ChildCodegen.java has the necessary boilerplate getter/setter methods, for example:

    public abstract class ChildCodegen extends AbstractDomainObject {

        ...
        private Integer id = null;
        private String name = null;
        private Integer version = null;
        private ForeignKeyHolder<Parent> parent = new ForeignKeyHolder<Parent>(Parent.class);
        ...

        // Validation rules are added based on the db constraints
        private void addExtraRules() {
            this.addRule(new NotNull<Child>(Shims.name));
            this.addRule(new MaxLength<Child>(Shims.name, 100));
        }

        public Integer getId() {
            return this.id;
        }

        public void setId(Integer id) {
            this.getChanged().record("id", this.id, id);
            this.id = id;
            if (UoW.isOpen()) {
                UoW.getIdentityMap().store(this);
            }
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.getChanged().record("name", this.name, name);
            this.name = name;
        }

        ...
    }