gpt4 book ai didi

java - 如何在 Spring Boot 中实现通用 JPA 存储库——它可以自动连接到任何实体/类类型的 spring 服务中

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:52:57 25 4
gpt4 key购买 nike

这是扩展了 spring PagingAndSortingRepository 的示例 Generic Repository 实现,

@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {

public List<T> findByNamedQuery( String name );
public List<T> findByNamedQueryAndParams( String name, Map<String, Object> params );
public T findOneByNamedQuery( String name );
public T findOneByNamedQueryAndParams( String name, Map<String, Object> params );

工厂 Bean 类,

public class GenericRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends
JpaRepositoryFactoryBean<R, T, I> {

@SuppressWarnings( "rawtypes" )
protected RepositoryFactorySupport createRepositoryFactory( EntityManager em )
{
return new MyRepositoryFactory(em);
}

private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

private final EntityManager em;

public MyRepositoryFactory( EntityManager em )
{
super(em);
this.em = em;
}

@SuppressWarnings( "unchecked" )
protected Object getTargetRepository( RepositoryMetadata metadata )
{
return new GenericRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), em);
}

protected Class<?> getRepositoryBaseClass( RepositoryMetadata metadata )
{
return GenericRepositoryImpl.class;
}
}
}

实现类,

public final class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements
GenericRepository<T, ID> {

private final EntityManager em;
private final Class<T> domainClass;

public GenericRepositoryImpl( Class<T> domainClass, EntityManager entityManager )
{
super(domainClass, entityManager);
this.em = entityManager;
this.domainClass = domainClass;
}

@Override
public List<T> findByNamedQuery( final String name )
{
validate(name);
return this.em.createNamedQuery(name, domainClass).getResultList();
}

@Override
public T findOneByNamedQuery( String name )
{
validate(name);
return this.em.createNamedQuery(name, domainClass).getSingleResult();
}

@Override
public List<T> findByNamedQueryAndParams( String name, Map<String, Object> params )
{
validate(name, params);
final TypedQuery<T> query = this.em.createQuery(name, domainClass);
setParams(query, params);
return query.getResultList();
}

}

因此,当我尝试将 GenericRepository Autowiring 到不同类型(如 Customer.java、Message.java 等)的服务中时,它抛出至少需要一种 bean 类型的接口(interface) GenericRepository。如果我为客户和消息类型创建单独的存储库,这将起作用。如果不创建多个存储库,我无法实现这一点。

@Service
@Transactional( noRollbackFor = Exception.class )
public class CustomerService {

@Autowired
private GenericRepository<Customer, Serializable> cr; works fine with just one entity type

@Autowired
private GenericRepository<Message, Serializable> cr; throws exception

如果有 100 个或更多实体类,那么我最终会创建 100 个存储库,这很糟糕。如果有更好的方法,请告诉我。

最佳答案

就我所读到的内容而言,通过@Query 注释告诉新的接口(interface)方法做什么会更容易,并且不要为 BeanFactory 或 impl...而烦恼。

 @Repository
public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
@Query(value = "SELECT c FROM customers c WHERE c.name = :name")
public List<T> findByNamedQuery( String name );
...
}

Using generics in Spring Data JPA repositories

如果这对您不适用,并且您说您的代码适用于一个存储库,但在添加第二个存储库时失败,我的第一个想法是尝试将 bean 的范围设置为原型(prototype),但这只是一种推测。如果我没有真正帮到你,我很抱歉,不要太恨我^^

关于java - 如何在 Spring Boot 中实现通用 JPA 存储库——它可以自动连接到任何实体/类类型的 spring 服务中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33511537/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com