Java Spring/Hibernate/MySQL/JPA实体未保存
我正在尝试配置一个应用程序来使用spring数据JPA1.11.13 hibernate 5.2.10 spring 4.3.11.RELEASE 问题是实体没有被持久化到MySQL数据存储 POM相关性Java Spring/Hibernate/MySQL/JPA实体未保存,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data Jpa,我正在尝试配置一个应用程序来使用spring数据JPA1.11.13 hibernate 5.2.10 spring 4.3.11.RELEASE 问题是实体没有被持久化到MySQL数据存储 POM相关性 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-sup
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.10.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.11.13.RELEASE</version>
</dependency>
</dependencies>
实体等于/hashcode/getter/setter,用于保存字符
@Entity
@Table(name="property")
public class Property {
@EmbeddedId
private PropertyCompositeKey id;
@NotNull
@Column(name="url")
private String url;
@Column(name="main_pic")
@NotNull
private String mainPic;
@Column(name="lat")
@Min(-180)
@Max(180)
@NotNull
private Double lat;
@Column(name="lng")
@Min(-90)
@Max(90)
@NotNull
private Double lng;
@Column(name="type")
@NotNull
private String externalType;
@Column(name="name")
@NotNull
private String name;
@Column(name="description")
@NotNull
private String description;
@Column(name="num_bedrooms")
@Min(1)
@NotNull
private Integer numBedrooms;
@Column(name="num_bathrooms")
@Min(1)
@NotNull
private Integer numBathrooms;
@Column(name="max_occ")
@Min(1)
@NotNull
private Integer maxOcc;
@Column(name="country")
@Length(min=2,max=2)
@NotNull
private String country;
@Column(name="rating")
private Double rating;
@Column(name="num_raters")
private Integer numRaters;
@Column(name="rank")
private Double rank;
@Column(name="lowest_ppn")
@Min(1)
private Double lowestPpn;
@Column(name="max_ppn")
@Min(1)
private Double maxPpn;
@Column(name="avg_ppn")
@Min(1)
private Double avgPpn;
@Column(name="private_pool")
private Boolean privatePool;
@Column(name="pool")
private Boolean pool;
@Column(name="internet_access")
private Boolean internetAccess;
@Column(name="air_conditioning")
private Boolean airConditioning;
@Column(name="bbq")
private Boolean bbq;
@Column(name="satellite")
private Boolean satellite;
@Column(name="hot_tub")
private Boolean hotTub;
@Column(name="sauna")
private Boolean sauna;
@Column(name="parking")
private Boolean parking;
@Column(name="instant_book")
private Boolean instantBook;
@Column(name="updated")
@Version
private Timestamp updated;
public void setKey(String id, String supplierId) {
PropertyCompositeKey pck = new PropertyCompositeKey();
pck.setId(id);
pck.setSupplierId(supplierId);
this.id = pck;
}
}
可嵌入-复合主键
@Embeddable
public class PropertyCompositeKey implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6575008230123343148L;
@Column(name="id")
@NotNull
private String id;
@Column(name="supplier_id")
@NotNull
private String supplierId;
}
存储库
@Repository
public interface PropertyRepository extends JpaRepository<Property, PropertyCompositeKey> {
}
服务实现
@Service
public class PropertyServiceImpl implements PropertiesService {
@Autowired
private PropertyRepository repo;
@Override
@Transactional
public Property save(Property property) {
Property saved = repo.save(property);
return saved;
}
}
Spring配置类
@Configuration
@EnableJpaRepositories("property.dao")
@EnableTransactionManagement
@PropertySource(
value={"classpath:/properties.properties"},
ignoreResourceNotFound = false)
@ComponentScan(basePackages={"property.properties"})
public class PropertySpringConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public DataSource dataSource(@Value("${jdbc.driverClassName}") String driverClass,
@Value("${jdbc.url}") String url,
@Value("${jdbc.username}") String un,
@Value("${jdbc.password}") String pw,
@Value("${jdbc.minIdleConnections}") int mi,
@Value("${jdbc.initialPoolSize}") int is) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driverClass);
ds.setUrl(url);
ds.setUsername(un);
ds.setPassword(pw);
ds.setMinIdle(mi);
ds.setInitialSize(is);
return ds;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(new String[] { "property.entity" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory, DataSource ds) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(entityManagerFactory.getNativeEntityManagerFactory());
jtm.setDataSource(ds);
return jtm;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes=PropertySpringConfig.class)
public class TestRepository {
@Autowired
private PropertiesService propertyRepository;
@Test
@Commit
public void testRepository() {
Property p = new Property();
p.setKey("TEST_ID", "TEST_SUPPLIER");
p.setAirConditioning(true);
p.setAvgPpn(500.0);
p.setCountry("ES");
p.setDescription("TEST DESCRIPTION");
p.setExternalType("TEST");
p.setHotTub(false);
p.setLat(12.5);
p.setLng(45.6);
p.setLowestPpn(150.4);
p.setMainPic("TEST");
p.setMaxOcc(5);
p.setMaxPpn(777.4);
p.setName("TEST NAME");
p.setNumBathrooms(3);
p.setNumBedrooms(7);
p.setNumRaters(5);
p.setPrivatePool(true);
p.setRank(1.0);
p.setRating(4.5);
p.setUrl("TEST");
Property s = propertyRepository.save(p);
}
}
当我运行测试时,它会毫无错误地完成,但实体不会持久化。注销以保存:
调试:org.springframework.orm.jpa.JpaTransactionManager-创建
名为[property.service.PropertyServiceImpl.save]的新事务:
传播\需要,隔离\默认;
调试:
org.springframework.orm.jpa.JpaTransactionManager-新打开
实体管理器
[SessionImplPersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0}
更新=可执行列表{size=0}删除=可执行列表{size=0}
孤立删除=可执行列表{size=0}
collectionCreations=ExecutableList{size=0}
collectionRemovals=ExecutableList{size=0}
collectionUpdates=ExecutableList{size=0}
collectionQueuedOps=ExecutableList{size=0}
JPA事务的UnsolvedInsertDependencies=null]]
调试:
org.hibernate.engine.transaction.internal.TransactionImpl-开始
调试:org.springframework.orm.jpa.JpaTransactionManager-不是
公开JPA事务
[SessionImplPersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0}
更新=可执行列表{size=0}删除=可执行列表{size=0}
孤立删除=可执行列表{size=0}
collectionCreations=ExecutableList{size=0}
collectionRemovals=ExecutableList{size=0}
collectionUpdates=ExecutableList{size=0}
collectionQueuedOps=ExecutableList{size=0}
UnsolvedInsertDependencies=null]]作为JDBC事务,因为
JpaDialect[org.springframework.orm.jpa。DefaultJpaDialect@ccd1bc3]
不支持JDBC连接检索
调试:
org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionaAttribute资源
-添加具有以下属性的事务方法“save”:需要传播,默认隔离;
调试:
org.springframework.orm.jpa.JpaTransactionManager-发现线程绑定
实体管理器
[SessionImplPersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0}
更新=可执行列表{size=0}删除=可执行列表{size=0}
孤立删除=可执行列表{size=0}
collectionCreations=ExecutableList{size=0}
collectionRemovals=ExecutableList{size=0}
collectionUpdates=ExecutableList{size=0}
collectionQueuedOps=ExecutableList{size=0}
JPA事务的UnsolvedInsertDependencies=null]]
调试:
org.springframework.orm.jpa.JpaTransactionManager-参与
现有交易
调试:
org.springframework.orm.jpa.EntityManagerFactoryUtils-打开jpa
实体管理器
调试:
org.springframework.orm.jpa.EntityManagerFactoryUtils-注册
JPA EntityManager的事务同步
调试:
org.hibernate.event.internal.AbstractSaveEventListener-生成
标识符:组件[id,supplierId]{supplierId=测试供应商,
id=TEST_id},使用策略:
org.hibernate.id.CompositeNestedGeneratedValueGenerator
调试:
org.springframework.orm.jpa.EntityManagerFactoryUtils-关闭jpa
实体管理器
调试:org.springframework.orm.jpa.JpaTransactionManager
-启动事务提交
调试:org.springframework.orm.jpa.JpaTransactionManager-提交jpa
EntityManager上的事务
[SessionImplPersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0}
更新=可执行列表{size=0}删除=可执行列表{size=0}
孤立删除=可执行列表{size=0}
collectionCreations=ExecutableList{size=0}
collectionRemovals=ExecutableList{size=0}
collectionUpdates=ExecutableList{size=0}
collectionQueuedOps=ExecutableList{size=0}
unsolvedInsertDependencies=null]]
调试:
org.hibernate.engine.transaction.internal.TransactionImpl-提交
调试:org.springframework.orm.jpa.JpaTransactionManager-关闭jpa
实体管理器
[SessionImplPersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0}
更新=可执行列表{size=0}删除=可执行列表{size=0}
孤立删除=可执行列表{size=0}
collectionCreations=ExecutableList{size=0}
collectionRemovals=ExecutableList{size=0}
collectionUpdates=ExecutableList{size=0}
collectionQueuedOps=ExecutableList{size=0}
事务后的UnsolvedInsertDependencies=null]]
调试:
org.springframework.orm.jpa.EntityManagerFactoryUtils-关闭jpa
实体管理器
调试:
org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener
-试验后方法:续
分机[DefaultTestContext@50f8360dtestClass=TestRepository,testInstance=property。TestRepository@61a485d2,
testMethod=testRepository@TestRepository,testException=[null],
mergedContextConfiguration=[MergedContextConfiguration@2cb4c3ab
testClass=TestRepository,位置={},类={class
property.spring.config.PropertySpringConfig},
ContextInitializerClass='[]',activeProfiles='{}',
propertySourceLocations='{}',propertySourceProperties='{}',
contextCustomizers=set[[empty]],contextLoader=
'org.springframework.test.context.support.AnnotationConfigContextLoader',
parent=[null]],用@DirtiesContext[false]注释的类,带有
mode[null],用@DirtiesContext[false]注释的方法,带mode
[null]。
调试:
org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener
-测试类之后:上下文[DefaultTestContext@50f8360dtestClass=TestRepository,testInstance=[null],testMethod=[null],
testException=[null],mergedContextConfiguration=
[MergedContextConfiguration@2cb4c3abtestClass=TestRepository,
位置='{}',类='{class
property.spring.config.PropertySpringConfig},
ContextInitializerClass='[]',activeProfiles='{}',
propertySourceLocations='{}',propertySourceProperties='{}',
contextCustomizers=set[[empty]],contextLoader=
'org.springframework.test.context.support.AnnotationConfigContextLoader',
parent=[null]],用@DirtiesContext[false]注释的类,带有
模式[null]。信息:
org.springframework.context.support.GenericaApplicationContext-
结束
org.springframework.context.support。GenericApplicationContext@643b1d11:
启动日期[英国夏令时2018年6月23日星期六12:53:04];上下文层次结构的根
信息:
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean-
正在关闭持久化单元“默认”的JPA EntityManager工厂
调试:
org.hibernate.internal.SessionFactoryImpl-hh000031:关闭
调试:
org.hibernate.engine.spi.CascadeStyles-外部级联样式
regsition[persist:STYLE_persist]覆盖基本注册
[STYLE\u PERSIST\u SKIPLAZY]
调试:
org.hibernate.service.internal.AbstractServiceRegistryImpl-
在取消所有子系统的注册时隐式销毁ServiceRegistry
服务注册
调试:
org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl-
在取消所有注册时隐式销毁引导注册表
儿童服务登记处
当我将PropertyServiceImpl中的方法更改为使用JpaRepository的saveAndFlush方法时,测试包含以下带有错误的日志输出:
-为堆栈跟踪提供的标记为仅回滚异常的JDBC事务
Exception:Exception仅用于提供堆栈跟踪
位于org.hibernate.resource.transaction.backend.jdbc.internal.jdbResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.MarkRollbackOnly jdbResourceLocalTransactionCoordinatorImpl.java:255
位于org.hibernate.engine.transaction.internal.TransactionImpl.setRollbackOnlyTransactionImpl.java:143
位于org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.setrollbackonly JpaTransactionManager.java:655
位于org.springframework.orm.jpa.JpaTransactionManager.doSetRollbackOnlyJpaTransactionManager.java:566
位于org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollbackAbstractPlatformTransactionManager.java:860
位于org.springframework.transaction.support.AbstractPlatformTransactionManager.rollbackAbstractPlatformTransactionManager.java:830
位于org.springframework.transaction.interceptor.TransactionSpectSupport.CompleteTransactionAfterhowingTransactionAspectSupport.java:522
位于org.springframework.transaction.interceptor.TransactionSpectSupport.invokewithIntransactionTransactionSpectSupport.java:286
位于org.springframework.transaction.interceptor.TransactionInterceptor.invokeTransactionInterceptor.java:96
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
位于org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invokePersistenceExceptionTranslationInterceptor.java:136
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
位于org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invokeCrudMethodMetadataPostProcessor.java:133
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
位于org.springframework.aop.interceptor.ExposeInvocationInterceptor.invokeeexposeinvocationinterceptor.java:92
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
在org.spri
ngframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.InvokeSuroundingTransactionDetectorMethodInterceptor.java:57
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
位于org.springframework.aop.framework.JdkDynamicAopProxy.invokejdkddynamicaopproxy.java:213
位于com.sun.proxy.$Proxy51.saveandfluShun已知源
位于property.service.PropertyServiceImpl.savePropertyServiceImpl.java:19
在sun.reflect.NativeMethodAccessorImpl.invoke0Native方法中
位于sun.reflect.NativeMethodAccessorImpl.invokeUnknown源
在sun.reflect.DelegatingMethodAccessorImpl.invokeUnknown源
位于java.lang.reflect.Method.invokeUnknown源
位于org.springframework.aop.support.AopUtils.invokeJoinPointUsingReflectionAOutils.java:333
位于org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpointReflectiveMethodInvocation.java:190
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:157
位于org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocationTransactionInterceptor.java:99
位于org.springframework.transaction.interceptor.TransactionSpectSupport.invokewithIntransactionTransactionSpectSupport.java:282
位于org.springframework.transaction.interceptor.TransactionInterceptor.invokeTransactionInterceptor.java:96
位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceedReflectiveMethodInvocation.java:179
位于org.springframework.aop.framework.JdkDynamicAopProxy.invokejdkddynamicaopproxy.java:213
位于com.sun.proxy.$Proxy52.saveUnknown Source
testRepositoryTestRepository.java:62
在sun.reflect.NativeMethodAccessorImpl.invoke0Native方法中
位于sun.reflect.NativeMethodAccessorImpl.invokeUnknown源
在sun.reflect.DelegatingMethodAccessorImpl.invokeUnknown源
位于java.lang.reflect.Method.invokeUnknown源
位于org.junit.runners.model.FrameworkMethod$1.runReflectVeCallFrameworkMethod.java:50
位于org.junit.internal.runners.model.ReflectiveCallable.runReflectiveCallable.java:12
位于org.junit.runners.model.FrameworkMethod.invokeeexplosivelyframeworkmethod.java:47
位于org.junit.internal.runners.statements.InvokeMethod.evaluateInvokeMethod.java:17
位于org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluaterUnbeforetMethodCallbacks.java:75
位于org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.EvaluaterUnterTestMethodCallbacks.java:86
位于org.springframework.test.context.junit4.statements.SpringRepeat.evaluateSpringRepeat.java:84
位于org.junit.runners.ParentRunner.runLeafParentRunner.java:325
位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChildSpringJUnit4ClassRunner.java:252
位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChildSpringJUnit4ClassRunner.java:94
位于org.junit.runners.ParentRunner$3.runParentRunner.java:290
位于org.junit.runners.ParentRunner$1.scheduleParentRunner.java:71
位于org.junit.runners.ParentRunner.runChildrenParentRunner.java:288
访问org.junit.runners.ParentRunner.access$000ParentRunner.java:58
位于org.junit.runners.ParentRunner$2.evaluateParentRunner.java:268
位于org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluaterUnbeforetClassCallbacks.java:61
位于org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.EvaluaterUnterTestClassCallbacks.java:70
位于org.junit.runners.ParentRunner.runParentRunner.java:363
位于org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runSpringJUnit4ClassRunner.java:191
位于org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.runJUnit4TestReference.java:86
位于org.eclipse.jdt.internal.junit.runner.TestExecution.runTestExecution.java:38
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTestsRemoteTestRunner.java:459
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTestsRemoteTestRunner.java:678
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runRemoteTestRunner.java:382
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.mainRemoteTestRunner.java:192
我看不到我错过了什么
您能告诉我如何修复此问题并将实体持久化到数据存储中吗?您的问题是由于配置错误,HibernateJavaEndorapter不在Spring上下文中,因此您必须像Spring Bean一样声明它,示例如下:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(new String[] { "property.entity" });
em.setJpaVendorAdapter(vendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public JpaVendorAdapter vendorAdapter(){
return new HibernateJpaVendorAdapter();
}
问题是在初始化平台时使用LocalContainerEntityManagerFactoryBean,然后使用getNativeEntityManagerFactory方法
formTransactionManager bean。初始化事务管理器的正确方法是:
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf, DataSource ds) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(emf);
return jtm;
}
让Spring决定要通过的整个ManagerFactory
注意本文中的正确配置:
谢谢你的回答。我已经做了你建议的改变,但问题仍然存在。
DEBUG: org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(new String[] { "property.entity" });
em.setJpaVendorAdapter(vendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public JpaVendorAdapter vendorAdapter(){
return new HibernateJpaVendorAdapter();
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf, DataSource ds) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(emf);
return jtm;
}