【发布时间】:2016-02-28 10:15:41
【问题描述】:
我有一个基于 Spring Framework 的项目,它仅基于 Java 配置进行初始化。这意味着不需要使用 web.xml 文件。
您可以在下图中看到项目的结构:
使用的技术:
- Java 7
- Spring框架4.2.1.RELEASE
- 休眠 ORM 5.0.4.Final
- Spring Tool Suite IDE 3.6.2
- Maven 3
- 雄猫 7
初始化配置文件
“主”类称为 AppInitializer,它位于 initializer 文件夹下
AppInitializer
public class AppInitializer implements WebApplicationInitializer {
private static final String CONFIG_LOCATION = "com.project.app.config";
private static final String MAPPING_URL = "/";
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
WebApplicationContext context = getContext();
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(context));
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet",
new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(MAPPING_URL);
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(CONFIG_LOCATION);
return context;
}
}
..而我的配置类驻留在 config 文件夹中
WebMvcConfig
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "com.project.app" })
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private Environment env;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("hello");
}
@Bean
public ApplicationContextProvider applicationContextProvider() {
return new ApplicationContextProvider();
}
}
数据库配置文件
此时我想在我的项目中添加一个 postgres 数据库,因此我在 CONFIG_LOCATION 中创建了一个名为 db 的文件夹,这样春天就会“拿起" @Configuration 类。(使用 PGAdmin 创建新数据库后).. 我创建了以下配置类。
数据源
@Component
@PropertySource("classpath:application.properties")
public class DataSources {
@Autowired
private Environment env;
@Bean
@Primary
public DataSource dataSource() {
org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
String url = env.getProperty(SystemSettings.DS_URL);
String user = env.getProperty(SystemSettings.DS_USERNAME);
String pass = env.getProperty(SystemSettings.DS_PASSWORD);
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pass);
return ds;
}
}
而 SystemSettings 保存数据库的用户名、密码和 url
@Service
@Configuration
public class SystemSettings implements Settings {
public static final String DS_URL = "datasource.app.url";
public static final String DS_USERNAME = "datasource.app.username";
public static final String DS_PASSWORD = "datasource.app.password";
@Autowired
private Environment env;
@Override
public String get(String key) {
return env.getProperty(key);
}
}
这些值是从 application.properties 文件中提取的,如 DataSources 类中所示。
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=更新
datasource.app.type=POSTGRESQL
datasource.app.url=jdbc:postgresql://localhost:5432/app
datasource.app.username=用户 datasource.app.password=pass
实体和存储库
我继续添加一个实体类,它将代表项目中的一个简单表。 它位于 services/entities 文件夹内
停止JPA
@Entity
@Table(name = "stop")
public class StopJPA {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "description")
private String stopDescription;
@Column(name = "idStop")
private String idStop;
public StopJPA() {
}
public StopJPA(String stopDescription, String idStop) {
this.stopDescription = stopDescription;
this.idStop = idStop;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStopDescription() {
return stopDescription;
}
public void setStopDescription(String stopDescription) {
this.stopDescription = stopDescription;
}
public String getIdStop() {
return idStop;
}
public void setIdStop(String idStop) {
this.idStop = idStop;
}
}
然后我为这个表创建了一个存储库接口,它扩展了一个 CrudRepository。
停止存储库
/**
* Repository interface for StopJPA entities.
*/
@Repository
@RepositoryRestResource(collectionResourceRel = "stop", path = "stop")
public interface StopRepository extends CrudRepository<StopJPA, Long> {
StopJPA findById(@Param("id") Long id);
}
问题
在所有这些设置和配置之后,我设法让项目运行,但表没有在数据库中创建。
- 我在配置步骤中遗漏了什么?
- 如何让 Spring 扫描 JPA 实体并创建数据库?
我的主要意图是配置Spring(通过使用Spring Data JPA)和Hibernate,以使它们在不使用的情况下协同工作xml 配置文件,并且没有 Spring BOOT 依赖项。后者意味着必须“手动”配置环境。
更新
我在 DataSources 类中添加了一些配置,并将其重命名为
PersistenceContext
@Component
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class PersistenceContext {
@Autowired
private Environment env;
@Bean
@Primary
public DataSource dataSource() throws ClassNotFoundException {
org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
String url = env.getProperty(SystemSettings.DS_URL);
String user = env.getProperty(SystemSettings.USERNAME);
String pass = env.getProperty(SystemSettings.DS_PASSWORD);
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pass);
return ds;
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("com.project.app.services.entities");
Properties jpaProperties = new Properties();
// Configures the used database dialect. This allows Hibernate to create SQL
// that is optimized for the used database.
jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
// Specifies the action that is invoked to the database when the Hibernate
// SessionFactory is created or closed.
jpaProperties.put("hibernate.hbm2ddl.auto",
env.getRequiredProperty("hibernate.hbm2ddl.auto"));
// If the value of this property is true, Hibernate writes all SQL
// statements to the console.
jpaProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
// If the value of this property is true, Hibernate will format the SQL
// that is written to the console.
jpaProperties.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
/**
* Because we are using JPA, we have to create a transaction manager bean that integrates the
* JPA provider with the Spring transaction mechanism. We can do this by using the
* JpaTransactionManager class as the transaction manager of our application.
*
* We can configure the transaction manager bean by following these steps:
*
* -> Create a new JpaTransactionManager object. -> Configure the entity manager factory whose
* transactions are managed by the created JpaTransactionManager object.
**/
@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
Ans 还更新了属性文件
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.hbm2ddl.auto=创建-删除 hibernate.show_sql=false
hibernate.format_sql=truedatasource.app.type=POSTGRESQL
datasource.app.driverClassName=org.postgresql.Driver
datasource.app.url=jdbc:postgresql://localhost:5432/app
datasource.app.username=user datasource.app.password=pass
不幸的是,我得到了这个错误
严重:无法创建池的初始连接。 java.sql.SQLException: org.postgresql.Driver 在 ...... 引起: java.lang.ClassNotFoundException: org.postgresql.Driver 在......
我不知道为什么它给了我这个例外。 maven 依赖项在那里,驱动程序也在类路径中。 .有什么帮助吗?
【问题讨论】:
-
据我所知,这在 JPA 中是不可能的。您需要 Hibernate 并对其进行配置。
标签: spring postgresql jpa