Hej,
Chciałbym się was doradzić czy możliwe jest programowanie w Javie "pod interfejsy" i jednocześnie używania Hibernate.
Poniżej mój problem jeżeli chodzi o łączenie poprawnego stylu programowania i tego frameworka:
Programując "pod klasy" - tzn nie używając interfejsów bardzo łatwo wszystko jest w Hibernate zmapować. Chciałbym jednak zrobić to nieco ładniej, co w przyszłości miało by mi ułatwić życie. Tylko okazuje się że to nie jest takie proste. Wymyśliłem sobie:
Interfejs Identifiable - jedyna metoda to ta, która pozwala na pobranie klucza głównego danego obiektu. Nie ma metody ustawiającej. Chciałbym aby taki klucz ustawiany był raz a potem nie zmieniany (zresztą niektóre bazy danych na to nie pozwalają). Hibernate będzie w stanie ten klucz ustawić przy tworzeniu obiektu bo dobierze się do pola odpowiedniej klasy. Tutaj tylko będzie pobieranie klucza:
public interface Identifiable {
Long getId();
}
zaimplementujmy sobie relację many-to-many z użyciem interfejsów. Mamy graczy i drużyny - wiele graczy może grać w jednej drużynie, jeden gracz może grać w wielu drużynach. No to jazda:
public interface Player extends Identifiable {
String getName();
void setName(String name);
Set<Team> getTeams();
void setTeams(Set<Team> teams);
void addTeam(Team team);
}
public interface Team extends Identifiable {
String getName();
void setName(String name);
Set<Player> getPlayers();
void setPlayers(Set<Player> players);
void addPlayer(Player player);
}
public class PlayerImpl implements Player {
// tutaj dopiero bedzie deklarowane id!!!
private Long id;
private String name;
private Set<Team> teams;
public PlayerImpl() {
}
public Set<Team> getTeams() {
return teams;
}
public void setTeams(Set<Team> teams) {
this.teams = teams;
}
public void addTeam(Team team) {
teams.add(team);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
}
public class TeamImpl implements Team {
private Long id;
private String name;
private Set<Player> players;
public TeamImpl() {
}
public Set<Player> getPlayers() {
return players;
}
public void setPlayers(Set<Player> players) {
this.players = players;
}
public void addPlayer(Player player) {
players.add(player);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
}
i teraz jest pytanie jak to zmapować?
Próbuję tak:
<?xml version="1.0" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="PlayerImpl" table="PLAYERS">
<id name="id" column="ID" access="field">
<generator class="sequence">
<param name="sequence">PLAYERS_SEQUENCE</param>
</generator>
</id>
<property name="name" column="NAME"/>
<!-- many-to-many relationship -->
<set name="teams" table="PLAYERS_TEAMS">
<key column="PLAYER_ID"/>
<many-to-many column="TEAM_ID" class="Team"/> <!-- tutaj podalem interfejs! pojdzie? -->
</set>
</class>
<class name="TeamImpl" table="TEAMS">
<id name="id" column="ID" access="field">
<generator class="sequence">
<param name="sequence">TEAMS_SEQUENCE</param>
</generator>
</id>
<property name="name" column="NAME"/>
<!-- many-to-many relationship -->
<set name="players" table="PLAYERS_TEAMS">
<key column="TEAM_ID"/>
<many-to-many column="PLAYER_ID" class="Player"/> <!-- tutaj takze interfejs -->
</set>
</class>
</hibernate-mapping>
Niestety, nie za bardzo chce to współpracować. Drze się, że nie zmapowałem interfejsów.
Tylko tutaj staje pod ścianą bo nie zawsze da się zmapować interfejs (w obie strony oczywiście - tworzenie i zapisywanie z / do bazy). Dlaczego - otóż wynik działania jakiejś metody z interfejsu może być wynikiem działania wielu metod z implementującej go klasy (jakieś dodawania pól chociażby).
Albo lepiej - przykład z góry - mój interfejs nie zawiera żadnego pola które można by uznać za jego klucz głowny - więc hibernate nie pozwoli mi tego zmapować. Nie chce w interfejsie umieszczać pola "id", bo było by one publiczne i ogólnie dostępne jadąc w dół po całej hierarchii...
Czy w ogóle taki styl programowania w Hibernate jest możliwy? Z tego co oglądam jakieś opensourcowe projekty oparte na Hibernate to raczej wszyscy jadą w nich "pod klasy".
Pozdrawiam!