Spring JPA и persistence.xml
Я пытаюсь настроить простой WSA файл Spring JPA Hibernate для развертывания в Glassfish.
Я вижу, что в некоторых примерах используется файл persistence.xml, а другие - нет.
В некоторых примерах используется dataSource, а некоторые нет. До сих пор я понимаю, что dataSource не нужен, если у меня есть:
<persistence-unit name="educationPU"
transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.coe.jpa.StudentProfile</class>
<properties>
<property name="hibernate.connection.driver_class"
value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/COE" />
<property name="hibernate.connection.username" value="root" />
<property name="show_sql" value="true" />
<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
Я могу развернуть отлично, но мой EntityManager не вводится Spring.
Мое приложениеContext.xml:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="educationPU" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="StudentProfileDAO" class="com.coe.jpa.StudentProfileDAO">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="studentService" class="com.coe.services.StudentService">
</bean>
Мой класс с EntityManager:
public class StudentService {
private String saveMessage;
private String showModal;
private String modalHeader;
private StudentProfile studentProfile;
private String lastName;
private String firstName;
@PersistenceContext(unitName="educationPU")
private EntityManager em;
@Transactional
public String save()
{
System.out.println("*** em: " + this.em); //em is null
this.studentProfile= new StudentProfile();
this.saveMessage = "saved";
this.showModal = "true";
this.modalHeader= "Information Saved";
return "successs";
}
Мой web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
Есть ли какие-либо фрагменты, которые мне не хватает, чтобы Spring вводить "em" в StudentService?
Ответы
Ответ 1
Просто чтобы подтвердить, хотя вы, вероятно, сделали...
Включили ли вы
<!-- tell spring to use annotation based congfigurations -->
<context:annotation-config />
<!-- tell spring where to find the beans -->
<context:component-scan base-package="zz.yy.abcd" />
в вашем приложении context.xml?
Также я не уверен, что вы сможете использовать тип транзакции jta с такой настройкой? Разве это не потребует пула подключений с источником данных? Поэтому попробуйте RESOURCE_LOCAL.
Ответ 2
Я в замешательстве. Вы вводите PU в сервисный слой, а не в слой persistence? Я этого не понимаю.
Я добавляю слой сохранения в сервисный уровень. Уровень обслуживания содержит бизнес-логику и демаркирует границы транзакций. Он может включать в транзакцию несколько DAO.
Я не получаю магию в методе save(). Как сохранены данные?
В процессе производства я настраиваю spring следующим образом:
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/ThePUname" />
вместе со ссылкой в web.xml
Для модульного тестирования я делаю это:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:persistence-xml-location="classpath*:META-INF/test-persistence.xml"
p:persistence-unit-name="RealPUName" p:jpaDialect-ref="jpaDialect"
p:jpaVendorAdapter-ref="jpaVendorAdapter" p:loadTimeWeaver-ref="weaver">
</bean>
Ответ 3
У меня есть тестовое приложение, настроенное с использованием JPA/Hibernate и Spring, и моя конфигурация отражает ваши данные, за исключением того, что я создаю источник данных и вставляю его в EntityManagerFactory, и перенесил свойства данных с использованием источника данных из persistenceUnit и в источник данных. При этих двух небольших изменениях мой EM вводится правильно.
Ответ 4
Это может быть старым, но если у кого-то есть такая же проблема, попробуйте изменить unitname, чтобы просто указать в аннотации PersistenceContext:
С
@PersistenceContext(unitName="educationPU")
к
@PersistenceContext(name="educationPU")
Ответ 5
Если кто-то хочет использовать конфигурацию Java чисто вместо xml
конфигурации hibernate, используйте это:
Вы можете настроить Hibernate без использования persistence.xml вообще в Spring, например:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}
Поскольку вы не используете persistence.xml, вы должны создать bean, который возвращает DataSource, указанный вами в указанном выше методе, который устанавливает источник данных:
@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}
Затем вы используете аннотацию @EnableTransactionManagement
для этого файла конфигурации. Теперь, когда вы помещаете эту аннотацию, вам нужно создать последний bean:
@Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}
Теперь не забывайте использовать @Transactional
Аннотацию к тем методам, которые имеют дело с БД.
Наконец, не забудьте ввести EntityManager
в ваш репозиторий (этот класс репозитория должен иметь аннотацию @Repository
над ним).