当前位置: 首页 > 知识库问答 >
问题:

如何通过Xml配置连接JpaRepository(的子类/子接口)?

丌官炎彬
2023-03-14

如何通过Xml配置连接JpaRepository的a(子类/子接口)?

所以我有一个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);
}

问题出在应用程序上下文.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

interface MyDepartmentJpaRepo extends JpaRepository<Department, Long>

因此,当您尝试用xml定义IoC/DI时,您会得到“interface not allowed for non-abtractbean”。

这看起来像是第二十二条军规......:(

神奇的问题:

如何将xml-config用于IoC/DI...................利用一个子接口的JpaRepository????

追加:

如果我添加“jpa:存储库”,那么我没有“管理器”的构造函数参数。

http://www . spring framework . org/schema/beans/spring-beans . xsd http://www.springframework.org/schema/data/jpa https://www . spring framework . 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}

共有2个答案

姚树
2023-03-14

另一个答案远比这个答案简单,也更好。(来自“R.G .”的回答)。然而,我确实为未来的读者找到了一个丑陋的变通方法。

不要喜欢这个答案,而不是来自R. G.的答案!

import org.springframework.stereotype.Component;

import javax.inject.Inject;

@Component
public class DepartmentJpaRepositoryFactory {

    @Inject
    private MyDepartmentJpaRepo autoinjectedDepartmentJpaRepositoryWorkaround;

    /* this is a workaround for using explicit xml IOC with spring-data.
    * because it is "interface MyDepartmentJpaRepo" (not a class), you cannot do traditional xml IoC definitions :(
    * this is a workaround.  this factory should NEVER be used by the code base, only by spring-di  */
    public MyDepartmentJpaRepo getInstanceDepartmentJpaRepository() {
        return this.autoinjectedDepartmentJpaRepositoryWorkaround;
    }
}

然后是应用程序上下文.xml

    <jpa:repositories base-package="com.blah.blah.blah.jpa.repositories" />

<bean id="DepartmentManagerBean" class="com.blah.blah.blah.managers.DepartmentManager">
    <constructor-arg ref="DepartmentJpaRepositoryViaFactoryMethodBean"/>
</bean>

<bean id="DepartmentJpaRepositoryServiceLocatorBean" class="com.blah.blah.blah.jpa.factories.DepartmentJpaRepositoryFactory">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="DepartmentJpaRepositoryViaFactoryMethodBean"
      factory-bean="DepartmentJpaRepositoryServiceLocatorBean"
      factory-method="getInstanceDepartmentJpaRepository"/>

以上是一个丑陋和令人讨厌的解决方法,使用

https://docs . spring . io/spring/docs/current/spring-framework-reference/core . html # beans-factory-class-instance-factory-method

"使用实例工厂方法进行实例化"

荆弘伟
2023-03-14

基于参考文档:XML 配置

以下配置工作基于以下理解:

每个bean都注册在派生自接口名称的bean名称下,因此UserRepository的接口将注册在userRepository下。

所以接口的豆名

public interface MyDepartmentJpaRepo extends JpaRepository<Department, Long> {
..
}

将如下所示: 我的部门Jpa回复

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
     https://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">

   <jpa:repositories base-package="com.mycompany.organizationdemo.businesslayer.repository"/>

    <bean id="IDepartmentManagerBean" class="com.mycompany.organizationdemo.businesslayer.managers.DepartmentManager">
        <constructor-arg ref="myDepartmentJpaRepo"/>
    </bean>
</beans>

为了验证,我自动装配并使用了DepartmentManager实例,如下所示

@Autowired
IDepartmentManager manager;

Spring开机版本:2.2.6

文档还提到了以下内容

一种方法是使用每个支持存储库机制的Spring Data模块随附的Spring命名空间,尽管我们通常建议使用Java配置。

注意:程序包名称已修改以匹配问题,请根据需要进行修改。

希望这能有所帮助。

 类似资料:
  • 我想要的是,在不编写setup()方法的情况下,如何连接(或引用)两个xml(parent-xml和child-xml)? 在setup()方法中,有一些使context.xml child-xml connect(连接context.xml和child-xml)的逻辑(cording)。但我认为还有另一种方法可以把它们联系起来。Alredy我试着写了 在contextsub.xml中,但它不起作

  • 我对配置SJMS2组件的最佳方法感到困惑。我正在一个简单的测试应用程序中使用,并尝试使用SJMS2camel组件从编写到ActiveMQ Artemis。组件文档说它处理连接缓存之类的事情,我通常会在ConnectionFactory bean中配置这些事情,所以我感觉到在配置中应该比不使用Camel时定义的更少。 在使用Camel Spring时,文档似乎缺少如何配置jsms2路由及其Conne

  • 问题内容: 我有以下代码: 并且在编译时给出错误: 我如何使用它来执行查询并检索其值。 谢谢 PS:与数据库的连接正在工作..(如果我取消注释该行,它将打印“ connected”)。 问题答案: 这是非常糟糕的代码-书面上没有用。您有很多工作要做。 我建议您研究一下并丢弃代码:

  • 我目前正在着手一个将spring数据与JPA/Hibernate结合使用的项目。现在,我正在使用@Autowired注释在相关属性上注入JpaRepositories,例如: ...在这里,我员工道是一个扩展JpaRepository的接口,注释为@Repository: 使用这种方法一切都很好——然而,我相当习惯于用XML完成我的大部分Spring配置工作,因为我个人喜欢所有相关配置都在同一个地

  • 由于安全原因,一个测试人员不应该在采样器中看到另一个测试人员的jdbc配置详细信息,因为有可能误用用户名、密码和其他详细信息,所以我们有通用的测试机。 1、有没有办法为MySQL、DB2和Microsoft SQL等多个数据库的不同jdbc连接配置设置系统变量。例如:应用程序X使用Microsoft SQL,其中应用程序Y使用DB2,应用程序Z使用MySQL。Y和Z是集成层。数据库URL、JDBC

  • 使用mapr沙箱如果我尝试通过beeline连接到配置单元,使用以下命令: 它连接无问题 如果我尝试使用实际地址连接: 错误:无法使用JDBC URI:JDBC:hive2://192.168.48.138:10000:null(状态=08S01,代码=0)0:JDBC:hive2://192.168.48.138:10000(关闭)>打开客户端传输 我可以通过cli看到hiveserver2正在