如何解决Spring Data CRUD存储库:save方法不起作用
这根本不涉及Spring Boot。
我的英语会更好。
在Config下面使用Spring Data,我正在尝试执行DML请求。
完全是CrudRepository#save
方法。
但是我接下来要执行Spring的CrudRepository#save方法:
- 仅通过
hibernate.show_sql
功能记录选择。 - 对于hibernate.show_sql日志记录,没有执行任何“插入”或“更新”语句。
- 根本没有数据库更改。
================================================ =====
不确定,但这看起来像是交易问题。
似乎当时没有交易
因此事务CRUD Repos不能执行DML请求,
包括CrudRepository#save
。
也许配置有问题? 请随时查看,并随时询问其他信息。
更新: 下一个不良实践的解决方法帮助我达到了“更新”语句的执行水平。
//(autowired,shared entity manager)
entityManager.joinTransaction();
repository.save(user);
但是,这仍然是一种不好的做法。在这种情况下,Spring的目标就失去了。 无论如何,我需要使用基于声明式代码的事务管理。 问题仍未解决: 我的配置有什么问题? @Transactional注释仍然不起作用
用户域实体:
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User
{
@Id
@Column(name = "id_pk",length = 11)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int idPk;
@Column(name = "user_id",length = 25,nullable = false,unique = true)
private String userId;
@Column(name = "email_addr",length = 120)
private String email;
}
特定于域的Spring Data CRUD存储库声明:
public interface UserRepository extends CrudRepository<User,Integer> {
//nothing specific
}
Spring (无引导)基于代码的配置:
@EnableJpaRepositories(basePackages = "***",transactionManagerRef = "jpaTransactionManager")
@EnableTransactionManagement
public class DataConfig
{
@Bean
public EntityManagerFactory entityManagerFactory()
{
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource());
factory.setPackagesToScan(DOMAIN_ENTITY_SCAN_PACKAGE);
factory.setJpaVendorAdapter(getVendorAdapter());
factory.afterPropertiesSet();
return factory.getObject();
}
private HibernateJpaVendorAdapter getVendorAdapter()
{
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(Boolean.TRUE);
return vendorAdapter;
}
@Bean
public JpaTransactionManager jpaTransactionManager()
{
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
txManager.afterPropertiesSet();
return txManager;
}
}
解决方法
最后,我为我的案件找到了解决方案。
因为我使用的是Spring,没有Boot部分 我必须配置自定义 WebApplicationInitializer 来让Spring管理应用程序入口点:
public class MainWebAppInitializer implements WebApplicationInitializer
{
@Override
public void onStartup(final ServletContext sc)
{
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(WebAppConfiguration.class,DataConfig.class);
sc.addListener(new ContextLoaderListener(root));
...other not related code ommited
}
}
所以因为我已经使用 AnnotationConfigWebApplicationContext#register 注册了这两个配置类( WebAppConfiguration.class , DataConfig.class ) 我以为使用 @Configuration 注释配置会是Redundand。
那时候我错了。
要正确注册 TransactionManager ,您应该使用 @Configuration 注释您的Jpa Config类。
因此,我设法通过 @Configuration 注释我的配置类,这解决了我的问题。
现在,Spring CRUD存储库能够对DB运行DML查询(借助#save方法)。 准确地说:现在,存储库能够打开自己的事务并根据这些事务运行所需的查询。
,我没有得到,您如何初始化数据源属性?在您提供的代码中看不到。
factory.setDataSource(dataSource());
您应该像下面那样设计Configuration类。同时使用:
entityManagerFactoryRef="entityManagerFactory",transactionManagerRef="jpaTransactionManager"
从Yaml或属性文件中读取休眠属性。
并设置您的数据源
配置类:DataConfig
/**
* @author Som
*
*/
@Configuration
@EnableJpaRepositories(basePackages="package-name",entityManagerFactoryRef="entityManagerFactory",transactionManagerRef="jpaTransactionManager")
@EnableTransactionManagement
@PropertySource(value = { "classpath:application.yml" })
public class DataConfig {
@Autowired
private Environment environment;
@Value("${datasource.myapp.maxPoolSize:10}")
private int maxPoolSize;
/**
* Populate DataSourceProperties object directly from application.yml
* *
*/
@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.myapp")
public DataSourceProperties dataSourceProperties(){
return new DataSourceProperties();
}
/**
* Configure HikariCP pooled DataSource.
*
*/
@Bean
public DataSource dataSource() {
DataSourceProperties dataSourceProperties = dataSourceProperties();
HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder
.create(dataSourceProperties.getClassLoader())
.driverClassName(dataSourceProperties.getDriverClassName())
.url(dataSourceProperties.getUrl())
.username(dataSourceProperties.getUsername())
.password(dataSourceProperties.getPassword())
.type(HikariDataSource.class)
.build();
dataSource.setMaximumPoolSize(maxPoolSize);
return dataSource;
}
/**
* Entity Manager Factory setup.
*
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(new String[] { "package-name" });
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
factoryBean.setJpaProperties(jpaProperties());
return factoryBean;
}
/**
* Provider specific adapter.
*
*/
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
return hibernateJpaVendorAdapter;
}
/**
* Hibernate properties.
*
*/
private Properties jpaProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect",environment.getRequiredProperty("datasource.myapp.hibernate.dialect"));
properties.put("hibernate.hbm2ddl.auto",environment.getRequiredProperty("datasource.myapp.hibernate.hbm2ddl.method"));
properties.put("hibernate.show_sql",environment.getRequiredProperty("datasource.myapp.hibernate.show_sql"));
properties.put("hibernate.format_sql",environment.getRequiredProperty("datasource.myapp.hibernate.format_sql"));
if(StringUtils.isNotEmpty(environment.getRequiredProperty("datasource.myapp.defaultSchema"))){
properties.put("hibernate.default_schema",environment.getRequiredProperty("datasource.myapp.defaultSchema"));
}
return properties;
}
@Bean
@Autowired
public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory emf) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(emf);
return txManager;
}
}
application.yaml
server:
port: 8081
servlet:
context-path: /CRUDApp
---
spring:
profiles: local,default
datasource:
myapp:
url: jdbc:h2:~/test
username: SA
password:
driverClassName: org.h2.Driver
defaultSchema:
maxPoolSize: 10
hibernate:
hbm2ddl.method: create-drop
show_sql: true
format_sql: true
dialect: org.hibernate.dialect.H2Dialect
---
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。