问题:我正在设置Spring + JPA + MYSQL数据库。但是,一旦我进行了设置,我总会收到以下错误:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'lt.robot.dao.UserJPADaoImpl' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1090)
at lt.robot.main.App.main(App.java:15)
此问题已解决here。 因为我的配置文件是用Java编写的,所以我添加了注释(如下所示),现在它可以正常工作。
@EnableAspectJAutoProxy(proxyTargetClass = true)
问题:为什么需要它?我已经看过" Spring in Action第4版"," Spring Data",众多在线教程,但没有一个用AspectJProxy注释Config类。我的应用程序设置与在线发现的不同(甚至是Spring的github示例)。
我的设置
包结构:
lt.robot.main
App.class
AppConfig.class
lt.robot.entity
User.class
lt.robot.dao
UserJPADao.interface
UserJPADaoImpl.class
pom.xml依赖项
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
</dependencies>
App.class
import lt.robot.dao.UserJPADaoImpl;
import lt.robot.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
UserJPADaoImpl userDaoImpl = ctx.getBean(UserJPADaoImpl.class);
System.out.println(userDaoImpl.get(2));
User userNew = new User();
userNew.setUser_name("NewUser");
userDaoImpl.add(userNew);
}
}
AppConfig.class
@Configuration
@EnableTransactionManagement
@ComponentScan("lt.robot")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
@Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring1");
dataSource.setUsername("root");
dataSource.setPassword("pass");
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
HibernateJpaVendorAdapter vendorAdapter = new
HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.MYSQL);
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("lt.robot.entity");
factory.setDataSource(getDataSource());
return factory;
}
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(){
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
}
User.class
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private int user_id;
@Column(name = "user_name")
private String user_name;
//Getters & Setters
}
UserJPADaoImpl.class
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import lt.robot.dao.UserJPADao;
import lt.robot.entity.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional(transactionManager = "transactionManager")
public class UserJPADaoImpl implements UserJPADao {
@PersistenceContext
private EntityManager em;
public void add(User t) {
em.persist(t);
}
public User get(int id) {
return em.find(User.class, id);
}
}
答案 0 :(得分:1)
你的答案是here和here( bean使用的bean代理机制)
由于UserJPADaoImpl
类被标记为@Transactional
,因此在创建接口UserJPADao
时会为其创建基于JDK接口的默认代理。
语句ctx.getBean(UserJPADaoImpl.class)
表示Spring专门查找UserJPADaoImpl
类型的bean而不是UserJPADao
;这是默认创建的,如上所述。
因此,Spring应用程序上下文找不到任何类型UserJPADaoImpl
的bean,并遇到以下异常。
线程中的异常&#34; main&#34; org.springframework.beans.factory.NoSuchBeanDefinitionException:没有类型&#39; lt.robot.dao的限定bean。 UserJPADaoImpl &#39;可用
因此,要向Spring发出信号以查找特定的bean类型,您可以使用以下任何一种
ctx.getBean(UserJPADaoImpl.class)
查找实现类的bean查找它的接口类型bean UserJPADao
来自ctx.getBean(UserJPADao.class)
@EnableAspectJAutoProxy(proxyTargetClass = true)
主要是在教程中使用了第一种方法,因为你没有看到@EnableAspectJAutoProxy(proxyTargetClass = true)
的任何提及,因为它们依赖于基于默认JDK接口的代理和通过接口而不是其实现的bean查找。 / p>
如果您需要任何进一步的信息,请在评论中说明。
答案 1 :(得分:0)
由于您使用的是Spring-Data-JPA,我建议您使用JPARepository
inteface创建存储库,如下所示:
@Repository
public interface UserRepository extends JpaRepository<User, Serializable>{
User findByUser_id(int id);
}
在您的数据库配置中使用@EnableJpaRepositories
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.repository")
public class AppConfig {
..
..
..
}
创建服务,然后像这样自动装配UserRepository
并使用其方法。
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public User saveUser(User user){
return userRepository.save(user);
}
public List<User> getAllUsers(){
return userRepository.getAll();
}
public User getUserById(int id){
return userRepository.findByUser_id(id);
}
}
创建一个控制器并自动装配UserService
并使用其方法。