Статьи

Типизированные безопасные литералы свойств в запросах к базе данных или привязке данных

Вкратце: мы генерируем литералы безопасных типов с помощью lombok, чтобы помочь нам писать запросы к базе данных и привязку данных. Это весело.

Я почти не знаю ни одного языка, поддерживающего литералы свойств и методов. Литералы классов должным образом поддерживаются в Java и полезны во многих случаях. Поля или свойства литералов также могут позволить нам писать хорошие платформы. Например, Hibernate Criteria API использует  генератор Metamodel для создания литералов, которые можно использовать для построения безопасных типов запросов.

Нам также было удобно иметь эти литералы, поэтому мы создали lombok-ds, форк lombok-pg для автоматического создания этих литералов для нас. Если вы не знаете  проект ломбок , проверьте это, это весело и очень помогает!

Как правило , наша версия lombok создает статическое поле «_property» для свойств вашего Java-класса, которое отражает их имя и тип, а также может использоваться для получения и установки значения этого свойства в данном экземпляре.

Хорошая идея безопасных запросов без сгенерированных метаданных в Java 8 описана здесь: http://benjiweber.co.uk/blog/2013/12/28/typesafe-database-interaction-with-java-8/ . Для тех, кто не может ждать Java 8, эти сгенерированные литералы свойств могут быть лучшим вариантом. Он также не зависит от отражения, поэтому его также можно использовать с GWT.

Обратите внимание, что Joda Beans ( http://www.joda.org/joda-beans/ ) также является аналогичной платформой, и для тех, кто не может использовать lombok в своем проекте, это может быть хорошим выбором.

Примеры использования

Пример запроса к базе данных:

ds.query(Entity.class)
    .filterAttribute(Entity._stringAttribute)
    .valueEquals(“hello world”)
    .select().getAll();

An example of a value binding:

textBox.bind(model()
    .get(Model._person)
    .get(Person._age)
    .convert(new IntegerStringConverter()));

JSF value binding:

Value bindings can also be used in JSF. I wrote an article earlier (http://java.dzone.com/articles/creating-jsf-pages-pure-java ) on how we create JSF views from Java code. It’s even more useful if the EL expressions can be written type-safely, with compile-time checking. With these attribute literals, it’s easy and straightforward.

We are not currently planning to release our query builder, but we I will soon introduce our data binding solution, that will also be released as open source in a few weeks.

How to use it

To get the source, go to https://github.com/Doctusoft/ds-bean  and https://github.com/Doctusoft/lombok-ds . The binaries are not currently in any public repo, so you have to build it from the sources. Lombok-ds inherited an ant build, so you have to install the binary manually to your repository.

The dependencies are:

<dependency>
    <groupId>com.doctusoft</groupId>
    <artifactId>ds-bean</artifactId>
    <version>0.1.4</version>
</dependency>
<dependency>
    <groupId>com.doctusoft</groupId>
    <artifactId>lombok-ds</artifactId>
    <version>0.1.4</version>
</dependency>

To use it in eclipse, you have to run lombok-ds-0.1.4.jar and specify your eclipse installation directory. To use it with GWT, you have to add -javaagent:web-inf/lib/lombok-ds-0.1.4.jar=ECJ as a JVM parameter to the run configuration and to the GWT compiler. You can find further information about this in the lombok docs.

How it works

The Attribute interface is quite simple:

public interface Attribute<Holder, Value> {
    Value getValue( Holder instance );
    void setValue( Holder instance, Value value );
    Class<Holder> getParent();
    Class<Value> getType();
    String getName();
}

The name can be used well in building database queries, class instances are returned for runtime type checking and reflection, and the getter and setter methods can be used for entity mapping or value binding. And whatever you need them for.

We found that once you have these literals, they just turn out to be useful in many cases.

Our lombok fork creates the necessary code. This class for example:

public class Example {
    @Attribute
    private String value;
}

Will be expanded transparently, compile-time as:

public class Example {
    private String value;
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    private static final Attribute<Example, String> _value = new Attribute<Example, String>() {
        @Override
        public void setValue(Example instance, String value) {
            instance.setValue(value);
        }
        @Override
        public String getValue(Example instance) {
            return instance.getValue();
        }
        @Override
        public Class<String> getType() {
             return String.class;
        }
        @Override
        public Class<Example> getParent() {
            return Example.class;
        }
        @Override
        public String getName() {
             return "value";
	}
    };
}

Note that the getters and setters are also automatically generated. If you are working with Eclipse or Netbeans, these generated methods and fields will be visible instantly for content assist and outline.

Let us know in what other cases you find these literals useful!