Studio
Posted on June 24th, 2009 in Photo, RU | No Comments »
Впервые после Мишиных семинаров снимал в оборудованной студии. Ощущения феерические.
Впервые после Мишиных семинаров снимал в оборудованной студии. Ощущения феерические.
“… На выборах за кого голосовать - за Барака? Или за Обаму?”
JTL, the Java Tools Language (pronounced “Gee-tel”), is a high-level query language for selecting program elements, designed to serve the development of source code software tools for Java.
It is both simple and powerful: you may use it for various source code tasks, from just finding all classes with print() method to executing an extremely complex refactoring transformation.
JTL is very easy to use, its intuitive query-by-example syntax makes it really easy to write JTL queries. For example,
public static double method(int, int);
matches all static methods that receive two int parameters and return a
classWithFactory := is T, class { no public constructor; public static T method; }
matches all factory classes - classes having no public constructor, but instance factory method.
Additional JTL examples may be found in JTL Language Tour. The examples above come from this excellent manual too.
The JTL was initially described in the JTL - The Java Tools Language paper and developed at the Computer Science department at the Technion. But now, after a years of development, JTL goes open source at sourceforge. There is no blog or RSS feed there yet, but I hope those will appear soon.
Though claiming a blog at Technorati Profile is not so painful a it looks.
Also many-to-many associations are usually referenced as a bad design solution, they are widely used in almost all modern database-centric applications (especially in those built around the existing legacy database). The very common scenario is a case when you not only need to handle a many-to-many association but also hold some additional property on the association.
In a J2EE world, Hibernate still remains the most popular ORM tool (or the JPA provider, if you wish). But implementing such a scenario with Hibernate Annotations is not so simple as you might imagine.
First of all, in the good old spirit of the Hibernate community, there is almost no documentation about many-to-many associations and composite keys (two paragraphs stating that there is @ManyToMany and @EmbeddedId annotations are not considered a documentation).
And the second hope of every open-source tool consumer, the world wide web community, provides almost no help: everybody are referencing the same post by Marcel Panse, written in April 2006. Though Marsel’s post is very clean and descriptive, it become outdated and the solution provided there is simply not working with the latest versions of Hibernate Annotations.
So I had to reinvent the wheel by my own, based on Marsel’s sample. Below is the solution working with Hibernate Annotations 3.3.1.GA.
The database part is the same: we have three tables (item, product and product_item), two POJO classes, and two classes for a many-to-many association and its primary key. The main difference from Marsel’s solution is that I’m not using any kind of “fake” properties on ProductItem in order to reference Item and Product, but just a plain transient properties delegating to ProductItemPk.
@Entity @Table(name = "item") public class Item { private Integer id; private String name; private List<ProductItem> productItems = new LinkedList<ProductItem>(); public Item() { } @Id @GenericGenerator(name = "generator", strategy = "increment") @GeneratedValue(generator = "generator") @Column(name = "item_id", nullable = false) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "name") public String getName() { return this.name; } public void setName(String name) { this.name = name; } @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.item") public List<ProductItem> getProductItems() { return this.productItems; } public void setProductItems(List<ProductItem> productItems) { this.productItems = productItems; } }
@Entity @Table(name = "product") public class Product { private Integer id; private String name; private List<ProductItem> productItems = new LinkedList<ProductItem>(); public Product() { } @Id @GenericGenerator(name = "generator", strategy = "increment") @GeneratedValue(generator = "generator") @Column(name = "product_id", nullable = false) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "name") public String getName() { return this.name; } public void setName(String name) { this.name = name; } @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.product") public List<ProductItem> getProductItems() { return this.productItems; } public void setProductItems(List<ProductItem> productItems) { this.productItems = productItems; } }
Note the two important points: ProductItem has two transient properties for Product and Item (since an unidirectional relationships will be meaningless here) and a use of @AssociationOverrides annotation to specify the database columns
@Entity @Table(name = "product_item") @AssociationOverrides({ @AssociationOverride(name = "pk.item", joinColumns = @JoinColumn(name = "item_id")), @AssociationOverride(name = "pk.product", joinColumns = @JoinColumn(name = "product_id")) }) public class ProductItem { private ProductItemPk pk = new ProductItemPk(); @EmbeddedId private ProductItemPk getPk() { return pk; } private void setPk(ProductItemPk pk) { this.pk = pk; } @Transient public Item getItem() { return getPk().getItem(); } public void setItem(Item item) { getPk().setItem(item); } @Transient public Product getProduct() { return getPk().getProduct(); } public void setProduct(Product product) { getPk().setProduct(product); } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ProductItem that = (ProductItem) o; if (getPk() != null ? !getPk().equals(that.getPk()) : that.getPk() != null) return false; return true; } public int hashCode() { return (getPk() != null ? getPk().hashCode() : 0); } }
@Embeddable public class ProductItemPk implements Serializable { private Item item; private Product product; @ManyToOne public Item getItem() { return item; } public void setItem(Item item) { this.item = item; } @ManyToOne public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ProductItemPk that = (ProductItemPk) o; if (item != null ? !item.equals(that.item) : that.item != null) return false; if (product != null ? !product.equals(that.product) : that.product != null) return false; return true; } public int hashCode() { int result; result = (item != null ? item.hashCode() : 0); result = 31 * result + (product != null ? product.hashCode() : 0); return result; } }
Hope this helps.
После бурного обсуждения на работе выяснилось, что я делаю это не с той стороны, с которой это делают мои коллеги.
Чувствую себя остроконечником.
Объявление: “Ищется няня для ребенка 2.8″.
Странно, думаю, а почему фокусное расстояние не указано?
Утро, еду на работу. Полупустой вагон, в ушах - наушники, перед глазами - лептоп.
Через несколько сидений от себя замечаю религиозного мужика, накладывающего тфилин.
Всю дорогу каждый занят своим делом: мужик сосредоточено молится, я — читаю статью.
“Уважаемые пассажиры, бла, бла бла”. Ну, приехали наконец-то. Закрываю лептоп, сматываю провод от наушников. Напротив меня мужик абсолютно синхронно со мной закрывает молитвенник и начинает сматывать тфилин. Вытаскиваем сумки, упаковываемся, встаем и продвигаемся на выход.
The discussion is probably one of the best examples to the simple rule: programmers should never ever be allowed to lead a product design.
Для тех кто совсем не в курсе: OpenID — это открытая децентрализованная система единого входа, которая позволяет использовать один логин и пароль на большом количестве сайтов, которую придумал, угадайте кто (нет, не самизнаетекто, а Бред).
Для гиков, фриков и прочих тех, кому не лень: можно настроить у себя на сайте свой собственный OpenID провайдер с помощью phpMyID или PHP Standalone OpenID Server. Желаю успеха. Настроите - приходите, расскажете как было.
А для ленивых вроде меня: проще всего воспользоваться одним из существующих провайдеров и только немного подкрутиь свой сайт. Я настраивал свой блог на Wordpress 2.3.3 с помощью провайдера myOpenID
Первое: регистрируем. Заходим на https://www.myopenid.com/ и регистрируемся. В конце регистрации получаем свой собственный OpenID, например http://pupkin.myopenid.com. В принципе, с этим ID уже можно заходить на сайты, комментировать в ЖЖ и в этом блоге и прочая.
Второе: настраиваем. Делаем так, чтбы вместо http://pupkin.myopenid.com можно было писать http://vasya.pupkin.com. Для этого идем на свой сайт http://vasya.pupkin.com и вставляем в таг <head> следующие строчки:
<!-- Start myOpenId settings --> <link rel="openid.server" href="http://www.myopenid.com/server" /> <link rel="openid.delegate" href="http://pupkin.myopenid.com/" /> <link rel="openid2.local_id" href="http://pupkin.myopenid.com" /> <link rel="openid2.provider" href="http://www.myopenid.com/server" /> <meta http-equiv="X-XRDS-Location" content="http://www.myopenid.com/xrds?username=pupkin.myopenid.com" /> <!-- End myOpenId settings -->
И компот третье: проверяем. Идем в ЖЖ, или в комментарии к этой записи, или еще куда (в смысле, где можно заходить в OpenID, а не то, что вы подумали). В поле, которое отмечено значком
пишем http://vasya.pupkin.com и жмем на логин. Вас должно перебросить на страницу myOpenID для логина, а потом обратно, на страницу с комментариями.
Вот и все.