【发布时间】:2020-08-31 10:41:50
【问题描述】:
如何通过 Xml 配置连接 JpaRepository 的(子类/子接口)?
所以我有一个 JpaRepository 的“实现”
import org.springframework.data.jpa.repository.JpaRepository;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.Optional;
public interface MyDepartmentJpaRepo extends JpaRepository<Department, Long> {
/* "lookup strategy". see https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods */
Optional<Department> findDepartmentByDepartmentNameEquals(String departmentName);
Collection<Department> findByCreateOffsetDateTimeBefore(OffsetDateTime zdt);
}
和实体
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.OffsetDateTime;
@Entity
@Table(name = "DepartmentTable")
public class Department {
@Id
@Column(name = "DepartmentKey", unique = true)
@GeneratedValue(strategy = GenerationType.AUTO)
private long departmentKey;
@Column(name = "DepartmentName", unique = true)
private String departmentName;
@Column(name = "CreateOffsetDateTime", columnDefinition = "TIMESTAMP WITH TIME ZONE" )
private OffsetDateTime createOffsetDateTime;
public long getDepartmentKey() {
return departmentKey;
}
public void setDepartmentKey(long departmentKey) {
this.departmentKey = departmentKey;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
}
还有一个我需要注入 MyDepartmentJpaRepo 的类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
public class DepartmentManager implements IDepartmentManager {
private final Logger logger;
private final MyDepartmentJpaRepo deptRepo;
/* The Inject annotation marks which constructor to use for IoC when there are multiple constructors */
@Inject
public DepartmentManager(MyDepartmentJpaRepo deptRepo) {
this(LoggerFactory.getLogger(DepartmentManager.class), deptRepo);
}
public DepartmentManager(Logger lgr, MyDepartmentJpaRepo deptRepo) {
if (null == lgr) {
throw new IllegalArgumentException("Logger is null");
}
if (null == deptRepo) {
throw new IllegalArgumentException("IDepartmentDomainData is null");
}
this.logger = lgr;
this.deptRepo = deptRepo;
}
@Override
public Collection<Department> getAll() {
List<Department> returnItems = this.deptRepo.findAll();
return returnItems;
}
@Override
public Optional<Department> getSingle(long key) {
Optional<Department> returnItem = this.deptRepo.findById(key);
return returnItem;
}
@Override
public Optional<Department> getSingleByName(String deptName) {
Optional<Department> returnItem = this.deptRepo.findDepartmentByDepartmentNameEquals(deptName);
return returnItem;
}
public Collection<Department> getDepartmentsOlderThanDate(OffsetDateTime zdt)
{
Collection<Department> returnItems = this.deptRepo.findByCreateOffsetDateTimeBefore(zdt);
return returnItems;
}
@Override
public Department save(Department item) {
Department returnItem = this.deptRepo.save(item);
return returnItem;
}
}
以及“经理”的界面以确保完整性。
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.Optional;
public interface IDepartmentManager {
Collection<Department> getAll();
Optional<Department> getSingle(long key);
Optional<Department> getSingleByName(String deptName);
Department save(Department item);
Collection<Department> getDepartmentsOlderThanDate(OffsetDateTime zdt);
}
问题出在 applicationcontext.xml 中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="jpaSetup.di.xml"/>
<bean id="MyDepartmentJpaRepoBean" class="com.mycompany.blah.blah.blah.MyDepartmentJpaRepo">
</bean>
<bean id="IDepartmentManagerBean" class="com.mycompany.blah.blah.blah.DepartmentManager">
<constructor-arg ref="MyDepartmentJpaRepoBean"/>
</bean>
</beans>
所以..spring-boot-data 将(子接口的 JpaRepository)定义为一个接口
interface MyDepartmentJpaRepo extends JpaRepository<Department, Long>
因此,当您尝试对 IoC/DI 进行 xml 定义时,您会得到“interface not allowed for non-abtract beans”。
这看起来像是第 22 条 ...... :(
神奇的问题:
如何将 xml-config 用于 IoC/DI ......并利用子接口 JpaRepository ????
追加:
如果我添加“jpa:repositories”,那么我没有“manager”的构造函数参数。
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<import resource="jpaSetup.di.xml"/>
<jpa:repositories base-package="com.mycompany.blah.blah.blah" />
--> -->
<bean id="IDepartmentManagerBean" class="com.mycompany.organizationdemo.businesslayer.managers.DepartmentManager">
<constructor-arg ref="NotDoesNotExistMyDepartmentJpaRepoBean"/> <!-- DOES NOT WORK -->
</bean>
........
下面的其他文件以确保完整性。
jpaSetup.di.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans>
<bean id="myLocalContainerEntityManagerFactoryBeanBean"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.blah.blah.blah.entities"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${spring.jpa.show-sql}"/>
<property name="generateDdl" value="${spring.jpa.generate-ddl}"/>
</bean>
</property>
<!-- See https://stackoverflow.com/questions/16088112/how-to-auto-detect-entities-in-jpa-2-0/16088340#16088340 -->
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${spring.jpa.hibernate.ddl-auto}</prop>
<prop key="hibernate.dialect">${spring.jpa.properties.hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${SPRING_DATASOURCE_URL}"/>
<property name="username" value="${SPRING_DATASOURCE_USERNAME}"/>
<property name="password" value="${SPRING_DATASOURCE_PASSWORD}"/>
<property name="driverClassName" value="${SPRING_DATASOURCE_DRIVER-CLASS-NAME}"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myLocalContainerEntityManagerFactoryBeanBean"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="persistenceExceptionTranslationPostProcessor" class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
</beans>
和application.yml
spring:
jpa:
generate-ddl: true
show-sql: true
hibernate:
ddl-auto: update
naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
datasource:
url: ${SPRING_DATASOURCE_URL}
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
driverClassName: ${SPRING_DATASOURCE_DRIVER-CLASS-NAME}
【问题讨论】:
标签: spring-boot java-8 spring-data-jpa java-11