Java Spring数据CRUD存储库:保存方法不起作用
这与Spring Boot无关。 我的英语可以更好 我正在尝试对Spring数据使用下面的配置来执行DML请求 精确地Java Spring数据CRUD存储库:保存方法不起作用,java,spring,jpa,Java,Spring,Jpa,这与Spring Boot无关。 我的英语可以更好 我正在尝试对Spring数据使用下面的配置来执行DML请求 精确地crudepository#save方法 然而,执行Spring的crudepository#save方法,我将得到下一个: 只有选择被休眠。显示sql功能记录 对于hibernate.show\u sql日志记录,没有执行任何“insert”或“update”语句 数据库中没有任何更改 ==============================================
crudepository#save
方法
然而,执行Spring的crudepository#save方法,我将得到下一个:
crudepository#save
也许是配置有问题?
请看一看,并随时询问任何其他信息
更新:
下一个错误实践解决方案帮助我实现了“Update”语句的执行
//(autowired, shared entity manager)
entityManager.joinTransaction();
repository.save(user);
然而,这仍然是一种糟糕的实践方法。在这种情况下,弹簧的作用就失去了。
无论如何,我需要使用基于声明性代码的事务管理。
问题仍然悬而未决:
我的配置有什么问题@事务性批注仍然不起作用
用户域实体:
@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数据CRUD存储库声明:
public interface UserRepository extends CrudRepository<User, Integer> {
//nothing specific
}
我不明白,你是如何初始化数据源属性的?我无法在您给定的代码中看到
factory.setDataSource(dataSource());
您应该像下面这样设计您的配置类。使用以下两种方法:
entityManagerFactoryRef="entityManagerFactory",
transactionManagerRef="jpaTransactionManager"
从yaml或属性文件中读取hibernate属性
并设置您的数据源
配置类: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;
}
}
应用程序.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
---
最后,我为我的案子找到了解决办法 因为我使用的是没有启动部分的Spring 我必须配置自定义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注释configs是多余的
那一点我错了
要正确注册TransactionManager,您应该使用@Configuration注释您的Jpa配置类
因此,我设法用@Configuration注释了我的配置类,这就解决了我的问题
现在,Spring CRUD存储库能够对DB运行DML查询(借助于#save方法)。
精确地说:现在存储库可以打开自己的事务,并根据这些事务运行所需的查询。将id更改为非基本类型,以便它可以接受空值,否则,当您转到时,它将始终为PK 0insert@JLazar0谢谢你的建议,但是这一点与我上面描述的问题无关。谢谢你,Som。我隐藏了#dataSource方法,因为它的内部工作与上述问题无关。这肯定与数据源无关,因为在数据源配置方面,与db的所有通信都正常工作。正如我在上面的更新中提到的:使用entityManager#joinTransaction,一切都很好,尽管这是一种糟糕的做法。谢谢,我将尝试显式指定entityManagerFactoryRef。@MykytaChelombitko:没问题。啊,我明白了。是的,这不是关于数据源的,我理解。您可以在配置类中使用
entityManagerFactoryRef
和transactionManagerRef
尝试一次,正如我在代码中所描述的。不幸的是,这没有帮助。有趣的是,事务注释似乎正在工作。为什么?因为如果我不在方法/类上使用事务,我将无法加入事务。所以它看起来像是事务上下文或类似的东西之间的差异。不确定。@MykytaChelombitko:奇怪的是,我在我的一个项目中使用了多年相同的配置。您所说的@Transactional working是什么意思,您在服务类或服务方法中错过了这一点?最好在服务类中使用此anno。很高兴看到你的问题得到解决。
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
}
}