Some of posts from this blog has been moved to dywicki.pl. You will be automatically redirected to new blog if you would submit comment.
New posts are published on dywicki.pl, this blog contains old content related to Code-House company.


Niektóre posty z tego bloga zostały przeniesione do dywicki.pl. Zostaniesz automatycznie przekierowany jeśli bedzięsz chciał dodać komentarz.
Nowe posty sa publikowane na dywicki.pl, ten blog zawiera stare treści związane z firmą Code-House.

XML i Adnotacje – kod ogólnego przeznaczenia i JPA

W poprzednim wpisie przedstawiłem sposób na redukcję kodu w encjach przy pomocy dziedziczenia i adnotacji @MappedSuperclass. Rozwiązanie to możemy również stosować aby tworzyć kod bardziej przenośny, który niewielkim kosztem można użyć w innych projektach.


Większość aplikacji webowych stosuje autoryzację opartą o role (ang. Role Based Access Control), w takich wypadkach mamy zazwyczaj encję User oraz Role, pierwszą odpowiedzialną za przetrzymywanie informacji o użytkowniku a druga nazwy ról. O ile role są obszarem stałym – zawsze mają nazwę – o tyle użytkownicy często mają różne wariacje i relacje. Ot choćby powiązanie konta użytkownika z firmą.

// Copyright (C) 2009 Code-House
// All rights reserved
package org.code_house.security.domain;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.code_house.domain.BaseEntity;

/**
 * Klasa reprezentująca użytkownika. Powinna ona zostać nadpisana w docelowym
 * systemie poprzez plik orm.xml.
 * 
 * @author Łukasz Dywicki.
 */
@MappedSuperclass
public class SecurityUser extends BaseEntity {

    /**
     * Hasło użytkownika.
     */
    @Column
    private String password;

    /**
     * Login użytkownika.
     */
    @Column
    private String username;

    /**
     * Konto wygasło.
     */
    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar expire;

    /**
     * Grupy do których przynależy użytkownik.
     */
    @ManyToMany(mappedBy = "users")
    private Set<Role> roles;

    /**
     * Konto zablokowane np. po 3 nieudanych próbach logowania.
     */
    @Column
    private boolean locked;

    /**
     * Konto wyłączone np. przez administratora.
     */
    @Column
    private boolean enabled;

   // Dalej gettery i settery
}

Rola ma niekompletną definicję relacji do klasy SecurityUser, którą należy uzupełnić o informacje na temat encji docelowej i definicji tabeli pośredniczącej.

// Copyright (C) 2009 Code-House
// All rights reserved
package org.code_house.security.domain;

import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.code_house.domain.NamedEntity;

/**
 * Klasa reprezentująca rolę. Może to być np ADMIN, USER bądź cokolwiek innego.
 * 
 * @author Łukasz Dywicki luke@code-house.org
 */
@Entity
@Table(name = "roles")
public class Role extends NamedEntity {

    @ManyToMany
    @JoinTable(name = "users_roles",
        joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
    )
    private Set<SecurityUser> users;

    // gettery i settery
}

Oto kawałek konfiguracji XML, która uzupełni metadane i pozwoli na uruchomienie kodu. Atrybut target-entity pozwala na określenie tabeli docelowej relacji podczas gdy element inverse-join-column uzupełnia definicję tabeli pośredniczącej.

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="1.0" 
        xmlns="http://java.sun.com/xml/ns/persistence/orm"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">

    <package>org.code_house.security.domain</package>

    <entity class="Role">
        <attributes>
            <many-to-many name="users" target-entity="org.code_house.management.domain.User">
                <join-table>
                    <inverse-join-column name="user_id" referenced-column-name="id" />
                </join-table>
            </many-to-many>
        </attributes>
    </entity>
    <entity class="Memento">
        <attributes>
            <one-to-one name="user" target-entity="org.code_house.management.domain.User">
                <join-column name="user_id" />
            </one-to-one>
        </attributes>
    </entity>
</entity-mappings>

Przykład ten można wykorzystać by uzupełniać relacje, których nie sposób odzwierciedlić w kodzie.

 

2 replies


  1. is a


  2. Thank you for the good writeup. It actually was a leisure account it.
    Glance complex to far introduced agreeable from you!
    By the way, how could we be in contact?

Leave a reply