Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

Wstęp

Mechanizm wtyczek dostarcza narzędzi, które umożliwiają wtyczkom korzystanie z bazy danych. Zalecanym sposobem jest używanie biblioteki Hibernate.

Wtyczka może uzyskać dostęp do jakiejkolwiek bazy danych, jednak w tym rozdziale opisana zostanie tylko obsługa systemowej bazy danych.

Konfiguracja obiektów

W rozdziale Konfiguracja kontekstu wtyczki opisane zostało, w jaki sposób dodawać beany do kontekstu. Obsługa bazy danych bazować będzie na integracji SpringFramework i Hibernate. Opisana zostanie konfiguracja XML.

Aby zarejestrować SessionFactory wystarczy dodać taką deklarację bean'a. Obiekt automatycznie konfiguruje używany dialect, datasource etc.

plugin-context.xml
<bean id="sessionFactory" class="com.suncode.pwfl.persistence.support.hibernate.SystemBaseSessionFactoryBean">
	<property name="packagesToScan" value="com.suncode.plugin.tutorial" />
</bean>

Klasa com.suncode.pwfl.persistence.support.hibernate.SystemBaseSessionFactoryBean bazuje na klasie LocalSessionFactoryBean. Tam również znajduje się dokumentacja.

 

Prawdopodobnie chcemy także wykorzystać inne mechanizmy, które upraszczają kod transakcyjny:

plugin-context.xml
<!-- adnotacje @Transactional -->
<tx:annotation-driven/>
 
<!-- TransactionManager -->
<bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

Przykład działania

Teraz należy stworzyć naszą encję:

Note
@Entity
@Table(name = "pm_tutorial_note")
@SequenceGenerator(name = "note", sequenceName = "pm_tutorial_note_id")
public class Note {
 
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "note")
	private Long id;
 
	@Column(length = 2000)
	private String text;
 
	// getters...
	// setters...
}

Nazwy tabel, kolumn i sequencerów nie powinny przekraczać 30 znaków (limit Oracle)

 

Zapis i odczyt naszego obiektu może wyglądać tak:

NoteService
@Service
@Transactional
public class NoteService {
 
	@Autowired
	private SessionFactory sessionFactory;
 
	public void saveNote(Note note){
		sessionFactory.getCurrentSession().save(note);
	}
 
	public Note getNote(Long id){
		return (Note) sessionFactory.getCurrentSession().get(Note.class, id);
	}
}

Jakiekolwiek zmiany dokonane we wtyczce nie wymagają restartu serwera. Nawet zmiany mappingu hibernate są widoczne po aktualizacji wtyczki.

Wykorzystanie w mappingu systemowych encji

Może się zdarzyć, że w naszej encji potrzebujemy mapping np. na użytkownika systemu. W takim wypadku musimy zaimportować mapping użytkownika, żeby nasza instancja SessionFactory miała wszystkie potrzebne do zapisu w bazie danych informacje.

Import mappingów z systemu odbywa się podczas konfiguracji SessionFactory Hibernate'a:

plugin-context.xml
<bean id="sessionFactory" class="com.suncode.pwfl.persistence.support.hibernate.SystemBaseSessionFactoryBean">
	<property name="packagesToScan" value="com.suncode.plugin.tutorial" />
	
	<!-- Musimy zaimportować całe drzewo zależności -->
	<property name="importedMappings">
		<array>
			<value>com.suncode.pwfl.administration.user.User</value>
			<value>com.suncode.pwfl.administration.user.UserGroup</value>
			<value>com.suncode.pwfl.administration.structure.Position</value>
			<value>com.suncode.pwfl.administration.structure.OrganizationalUnit</value>
			<value>com.suncode.pwfl.administration.structure.Role</value>
		</array>
	</property>
</bean>

Aktualnie musimy samodzielnie wypisać wszystkie zależności, nawet te przejściowe. Jeżeli chcemy zaimportować tylko użytkownika, musimy zaimportować jeszcze 4 inne mappingi jak pokazano powyżej.

Planowane jest poprawienie sposobu importu mappingów.

 

Nasza zaktualizowana encja:

Note
@Entity
@Table(name = "pm_tutorial_note")
@SequenceGenerator(name = "note", sequenceName = "pm_tutorial_note_id")
public class Note {
 
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "note")
	private Long id;
 
	@Column(length = 2000)
	private String text;
	
	@ManyToOne
    @JoinColumn(name = "user_id")
    @OnDelete(action = OnDeleteAction.CASCADE)
	private User user;
 
	// getters...
	// setters...
}

Dodanie obiektu użytkownika do naszej encji zaowocuje dodaniem klucza obcego w schemacie bazy danych. Niestety w takim wypadku nie będzie możliwe usunięcie użytkownika z systemu, dopóki nie zostaną usunięte wszystkie jego notatki.

Adnotacja:

@OnDelete(action = OnDeleteAction.CASCADE)

Dodaje kaskadowe usuwanie na poziomie schematu bazy danych (w przeciwieństwie do opcji cascade annotacji), dzięki czemu podczas usuwania użytkownika, usunięte zostaną wszystkie jego notatki.

Potrzebne jest inne rozwiązanie tego problemu, jednak aktualnie jest to jedyna opcja.

 

 

 

  • No labels