制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)

Posted

技术标签:

【中文标题】制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)【英文标题】:Making Multiple EntityManagers (Spring-Boot-JPA, Hibernate, MSSQL) 【发布时间】:2015-10-20 04:51:41 【问题描述】:

我想连接到 2 个不同的数据库(MSSQL)。所以我喜欢下面。虽然我的 ProductController 有效,但 CustomerController 无效。添加客户控制器后,spring boot应用程序无法启动,因为它无法@AutowireCustomerDAO

这里出了什么问题,我该如何解决?

我所做的如下所示,

application.properties

DatabaseIP=myip
DatabasePort=1433
DB1DatabaseName=Test
DB2DatabaseName=Test2
DatabaseUser=sa
DatabasePwd=boomboom
#DB1
datasource.db1.url=jdbc:sqlserver://$DatabaseIP:$DatabasePort;databaseName=$DB1DatabaseName
datasource.db1.username=$DatabaseUser
datasource.db1.password=$DatabasePwd
datasource.db1.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver

datasource.db2.url=jdbc:sqlserver://$DatabaseIP:$DatabasePort;databaseName=$DB2DatabaseName
datasource.db2.username=$DatabaseUser
datasource.db2.password=$DatabasePwd
datasource.db2.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver

spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect

spring.jpa.show-sql=true

security.user.name=raj
security.user.password=raj123456

DB1EntityManager.java

@Configuration
@EnableTransactionManagement
@EnableAutoConfiguration
@EntityScan(basePackages = "com.rajkishan.db1Entities")
@EnableJpaRepositories(transactionManagerRef = "db1TransactionManager", entityManagerFactoryRef = "db1EntityManagerFactory", basePackages = "com.rajkishan.db1DAOs")
public class DB1EntityManager 

@Bean(name = "db1DataSource")
@Primary
@ConfigurationProperties(prefix = "datasource.db1")
public DataSource db1DataSource() 
    return DataSourceBuilder.create().build();


@Bean(name = "db1EntityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean db1EntityManagerFactory(final EntityManagerFactoryBuilder builder) 
    return builder
            .dataSource(db1DataSource())
            .build();


@Bean(name = "db1TransactionManager")
@Primary
public JpaTransactionManager db1TransactionManager(@Qualifier("db1EntityManagerFactory") final EntityManagerFactory emf) 
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
 

ProductDAO.java

@Transactional("db1TransactionManager")
public interface ProductDAO extends CrudRepository<Product, String>


ProductController.java

@RestController
@RequestMapping(value = "/product")
public class ProductController 

@Autowired
private EntityManager em;

@Autowired
private ProductDAO productDAO;

@RequestMapping(value = "/getinfo", method = RequestMethod.GET)
public String getProductInfo(@RequestParam(value = "model") String model) 
    try 
        Product product = productDAO.findOne(model);
        if (product == null) 
            return "No Data Found";
        
        String userName = "Maker for Model = " + model + " is "
                + product.getMaker()+ " and Type = " + product.getType();
        return userName;

     catch (Exception ex) 
        System.out.println(ex);
        return "Error Occured";
    

DB2EntityManager.java

@Configuration
@EnableTransactionManagement
@EntityScan(basePackages = "com.rajkishan.db2Entities")
@EnableJpaRepositories(transactionManagerRef = "db2TransactionManager", entityManagerFactoryRef = "db2EntityManagerFactory", basePackages = "com.rajkishan.db2DAOs")
public class DB2EntityManager 

@Bean(name = "db2DataSource")
@ConfigurationProperties(prefix = "datasource.db2")
public DataSource db2DataSource() 
    return DataSourceBuilder.create().build();


@Bean(name = "db2EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean db2EntityManagerFactory(final EntityManagerFactoryBuilder builder) 
    return builder
            .dataSource(db2DataSource())
            .build();


@Bean(name = "db2TransactionManager")
public JpaTransactionManager db2TransactionManager(@Qualifier("db2EntityManagerFactory") final EntityManagerFactory emf) 
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
 

CustomerDAO.java

@Transactional("db2TransactionManager")
public interface CustomersDAO extends CrudRepository<Customers, Integer>


CustomerController.java

@RestController
@RequestMapping(value = "/customer")
public class CustomerController 

@Autowired
private CustomersDAO customersDAO;

@Autowired
private EntityManager em;

@RequestMapping(value = "/getcustomerinfo", method = RequestMethod.GET)
public String getCustomerInfo(@RequestParam(value = "customerid") int cusId)
    try 
        Customers customer = customersDAO.findOne(cusId);
        if (customer == null) 
            return "No Data Found";
        
        String userName = "Name of Customer with CustomerID = " + cusId + " is "
                + customer.getFirstName()+ " " + customer.getLastName() + " and his AddressID = " + customer.getAddressId();
        return userName;

     catch (Exception ex) 
        System.out.println(ex);
        return "Error Occured";
    

错误日志

2015-07-29 14:29:53.834  INFO 4976 --- [main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default...]
2015-07-29 14:29:54.146  INFO 4976 --- [main] org.hibernate.dialect.Dialect: HHH000400: Using dialect:org.hibernate.dialect.SQLServerDialect
2015-07-29 14:29:54.167  INFO 4976 --- [main]o.h.h.i.ast.ASTQueryTranslatorFactory: HHH000397: Using ASTQueryTranslatorFactory
2015-07-29 14:29:54.262  WARN 4976 --- [main] o.h.j.i.EntityManagerFactoryRegistry: HHH000436: Entity manager factory name(default) is already
registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
2015-07-29 14:29:54.571  WARN 4976 --- [main]ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancel
ling refresh attempt

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerController': Injection of autowired dependencies failed; nested
exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.rajkishan.db2DAOs.CustomersDAO com.rajkishan.control
lers.CustomerController.customersDAO; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customersDAO':
 Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.rajkishan.db2Entities.Customers
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java
:334)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
        at com.rajkishan.Application.main(Application.java:20)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
        at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.rajkishan.db2DAOs.CustomersDAO com.rajkishan.controlle
rs.CustomerController.customersDAO; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customersDAO': I
nvocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.rajkishan.db2Entities.Customers
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.j
ava:561)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java
:331)
        ... 22 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customersDAO': Invocation of init method failed; nested excep
tion is java.lang.IllegalArgumentException: Not an managed type: class com.rajkishan.db2Entities.Customers
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.j
ava:533)
        ... 24 common frames omitted

Customers.java

    @Entity
@Table(name = "Customers", catalog = "Test2", schema = "dbo")
@XmlRootElement
@NamedQueries(
    @NamedQuery(name = "Customers.findAll", query = "SELECT c FROM Customers c"),
    @NamedQuery(name = "Customers.findById", query = "SELECT c FROM Customers c WHERE c.id = :id"),
    @NamedQuery(name = "Customers.findByFirstName", query = "SELECT c FROM Customers c WHERE c.firstName = :firstName"),
    @NamedQuery(name = "Customers.findByLastName", query = "SELECT c FROM Customers c WHERE c.lastName = :lastName"))
public class Customers implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "Id")
    private Integer id;
    @Size(max = 255)
    @Column(name = "first_name")
    private String firstName;
    @Size(max = 255)
    @Column(name = "last_name")
    private String lastName;
    @JoinColumn(name = "AddressId", referencedColumnName = "AddressId")
    @ManyToOne(optional = false)
    private Address addressId;

    public Customers() 
    

    public Customers(Integer id) 
        this.id = id;
    

    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    

    public String getFirstName() 
        return firstName;
    

    public void setFirstName(String firstName) 
        this.firstName = firstName;
    

    public String getLastName() 
        return lastName;
    

    public void setLastName(String lastName) 
        this.lastName = lastName;
    

    public Address getAddressId() 
        return addressId;
    

    public void setAddressId(Address addressId) 
        this.addressId = addressId;
    

    @Override
    public int hashCode() 
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    

    @Override
    public boolean equals(Object object) 
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Customers)) 
            return false;
        
        Customers other = (Customers) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) 
            return false;
        
        return true;
    

    @Override
    public String toString() 
        return "com.rajkishan.db2Entities.Customers[ id=" + id + " ]";
    


【问题讨论】:

为自动装配的依赖注入失败提供堆栈跟踪。如果它太长并且你不能剥离必需品,也许可以放一个链接 @LaurentiuL.:发布了堆栈跟踪。问题已更新。 CustomerDAO 是否在 com.rajkishan.db2DAOs 中? 发布您的客户类代码。我对注释感兴趣。我假设它在 com.rajkishan.db2Entities.Customers @LaurentiuL。 : 它是一个生成的实体类。问题已更新。 【参考方案1】:

在DAO类上添加@Repository注解,让spring知道它们。如下所示;

@Repository
@Transactional("db2TransactionManager")
public interface CustomersDAO extends CrudRepository<Customers, Integer>


【讨论】:

以上是关于制作多个 EntityManager(Spring-Boot-JPA、Hibernate、MSSQL)的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 中获取 EntityManager 的句柄

使用多个数据源时 Spring 中的多个实体管理器问题

不使用 Spring 获取 EntityManager

在 Spring 上实例化 EntityManager

Spring DaoSupport 和@PersistanceContext EntityManager?

Spring Boot-------JPA——EntityManager构建通用DAO