В сервер wildfly встроена реализация JPA, т. е. по умолчанию можно использовать библиотеки JPA hibernate четвертой версии, описывать сущности с помощью
аннотации @Entity. Давайте создадим приложение, которое
использует JPA, для
начала нужно определиться с базой данных. В wildfly уже есть встроенная база h2, используем её для наших целей. Заглянем в конфигурационный
файл JBOSS_HOME/Standalone/configuration/standalone.xml, там
должен быть настроен источник данных
который мы будем использовать:
<subsystem
xmlns="urn:jboss:domain:datasources:2.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS"
pool-name="ExampleDS" enabled="true"
use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver
name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
И так
напомню, мы будем использовать JPA
в web
приложении, опишем нашу сущность:
package
com.vit.model;
import
javax.persistence.Column;
import
javax.persistence.Entity;
import
javax.persistence.Id;
import
java.io.Serializable;
@Entity(name="persons")
public class
Person implements Serializable{
private static final long serialVersionUID
= 1L;
@Id
private Long Id;
@Column
private String myName;
public Person() {
}
….
Getters &
Setters
….
}
Опишем наш конфигурационный файл JPA, он должен находиться в директории web приложения jboss_ejb_war.war\WEB-INF\classes\META-INF\persistence.xml, а не в jboss_ejb_war.war\META-INF, рассмотрим его:
<?xml
version="1.0" encoding="UTF-8"?>
<persistence
version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit
name="primary">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>//наш источник данных h2
<class>com.vit.model.Person</class> // наш класс сущности
<properties>
<!-- Properties for Hibernate -->
<property
name="hibernate.hbm2ddl.auto" value="create-drop" />
<property
name="hibernate.show_sql" value="false" />
</properties>
</persistence-unit>
</persistence>
Напишем Stateless бин, и внедрим в него EntityManager:
package
com.vit;
import
com.vit.model.Person;
import
javax.ejb.Stateless;
import
javax.inject.Inject;
import
javax.persistence.EntityManager;
import
javax.persistence.PersistenceContext;
@Stateless
public class
EntityBean {
@PersistenceContext //Inject Ентити менеджер
private EntityManager em;
public void saveAs(String name){
Person p = new Person();
p.setId(1L);
p.setMyName(name);
Person p1 = null;
p1 = em.find(Person.class,p.getId());
if (p1==null) em.persist(p); else em.merge(p); //сохраняем нашу сущность
}
public String getName(){
return
em.find(Person.class,1L).getMyName(); // запрашиваем имя
}
}
Напишем jsp страничку, работающую с нашим EJB бином, смотрим код:
<%@ page
contentType="text/html;charset=UTF-8" %>
<%@ page
pageEncoding="UTF-8" %>
<%@ page
session="false" %>
<%@ page
import=" com.vit.EntityBean " %>
<%@ page
import="javax.naming.Context" %>
<%@ page import="javax.naming.InitialContext"
%>
<html>
<head>
<title>Home</title>
<meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8"/>
</head>
<body>
<h1>
Hello world!
</h1>
<%
Context context = new
InitialContext();
EntityBean calc2 = (EntityBean)
context.lookup("java:app/jboss_ejb_war/EntityBean!com.vit.EntityBean");
calc2.saveAs("Hello Session Stateful
Entity Bean!!!");//сохраняем наше значение в базе данных h2
out.println(calc2.getName());//выводим
наше значение из базы данных h2
%>
</body>
</html>
Как
обычно, осталось только развернуть приложение, вы всё должны запаковать в war архив и скопировать в каталог JBOSS_HOME/Standalone/deployments, после деплоя, запустите jsp страницу. Внимательный читатель,
который знаком с hibernate,
наверное, уже задается вопросом – “А где же транзакции?”. Транзакции
применяются по умолчанию ко всем EJB
бинам,
у нас есть аннотация @TransactionAttribute(value =
TransactionAttributeType.REQUIRED) которая является дефолтной и она по
умолчанию применяется ко всем методам, которые вы вызываете на сервере wildfly. Это все дело еще, когда метод автоматически
обёртывается в транзакцию, называют CMT (Container Management Transaction), т.е.
когда сервер за вас начинает транзакцию и завершает её. Т.е. к классу EntityBean который мы ранее написали, по
умолчанию применяются такие аннотации:
@Stateless
@TransactionManagement(value = TransactionManagementType.CONTAINER) //управляет транзакциями сервер
@TransactionAttribute(value = TransactionAttributeType.REQUIRED) //по умолчанию ко всем методам EJB применяется
уровень транзакции REQUIRED
public class
EntityBean {
@PersistenceContext //@Inject
private EntityManager em;
….
}
Если вы сами хотите
управлять транзакциями EJB
бина,
то вам нужно, во-первых выставить атрибут у аннотации в @TransactionManagement
в BEAN, затем добавить транзакции UserTransaction tx, и работать с этой транзакцией как вам
заблагорассудится, смотрим на наш переписанный EJB бин:
package
com.vit;
import
com.vit.model.Person;
import
javax.annotation.Resource;
import
javax.ejb.*;
import
javax.inject.Inject;
import
javax.persistence.EntityManager;
import
javax.persistence.PersistenceContext;
import
javax.transaction.*;
@Stateless
@TransactionManagement(value
= TransactionManagementType.BEAN)
public class
EntityBean {
@PersistenceContext //@Inject
private EntityManager em;
@Resource
UserTransaction tx;
public void saveAs(String name) {
Person p = new Person();
p.setId(1L);
p.setMyName(name);
Person p1 = null;
try {
tx.begin(); //начинаем транзакцию
p1 = em.find(Person.class,
p.getId());
if (p1 == null) em.persist(p);
else em.merge(p);
tx.commit();//подтверждаем транзакцию
} catch (RollbackException e) {
e.printStackTrace();
} catch (HeuristicMixedException e) {
e.printStackTrace();
} catch (HeuristicRollbackException e)
{
e.printStackTrace();
} catch (NotSupportedException e) {
e.printStackTrace();
} catch (SystemException e) {
e.printStackTrace();
}
}
public String getName() {
String s = null;
try{
tx.begin();
s = em.find(Person.class,
1L).getMyName();
tx.commit();
} catch (RollbackException e) {
e.printStackTrace();
} catch (HeuristicMixedException e) {
e.printStackTrace();
} catch (HeuristicRollbackException e)
{
e.printStackTrace();
} catch (NotSupportedException e) {
e.printStackTrace();
} catch (SystemException e) {
e.printStackTrace();
}
return s;
}
}