Spring QueryDSL从Spring Context设置Session

时间:2014-04-16 15:54:10

标签: spring hibernate jpa

我正在研究QueryDSL库并将其实现到我的DAL项目中。

我清楚的是,我需要实例化一个HibernateQuery对象并使用QueryDSL方法来定义数据源(from()子句)和条件(where()和BooleanExpressions)。 例如,考虑具有name字段的用户实体,并假设我们要测试名称等于“Richie”的用户是否存在于DB中。我会编写以下代码来完成任务

public boolean richieExists()
{

    QUser qUser = QUser.user;       
    HibernateQuery query = new HibernateQuery(session); // I need a session instance here!
    User richie = query.from(qUser).where(qUser.name.eq("Richie")).uniqueResult(qUser);

    return (richie!=null);

}

问题是上面的代码应该是Spring的Service对象的方法,它使用Repository来执行CRUD操作。这意味着我需要从我在Application Context中使用的EntityManager实例中检索Session以实例化HibernateQuery对象,这是一个问题,因为Service对象没有办法返回使用的EntityManager的。

编写QueryDSL查询的正确方法/地点是什么?

这是我的带有Spring配置的DAOConfig.java类(这里我们定义了Spring用于存储库操作的EntityManagerFactoryBean)

package my.dal.service.dal.config;

import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan(basePackages = { "my.dal" })
@PropertySource("classpath:dbconnection.properties")
@EnableJpaRepositories("my.dal.repository")
@EnableTransactionManagement
public class DALConfig {


    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver_class";  
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";  
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";  
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";  

    private static final String PROPERTY_NAME_POOL_INITIAL_SIZE = "pool.initialsize";
    private static final String PROPERTY_NAME_POOL_MAX_IDLE = "pool.maxidle";
    private static final String PROPERTY_NAME_DAL_CLASSES_PACKAGE = "entities.packages_to_scan";  
    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.showsql";
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";

    @Resource
    private Environment environment;  


    @Bean
    public DataSource dataSource()
    {

        Properties props = new Properties();


        props.put("driverClassName", environment.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        props.put("url", environment.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        props.put("username", environment.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        props.put("password", environment.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
        props.put("initialSize", environment.getRequiredProperty(PROPERTY_NAME_POOL_INITIAL_SIZE));
        props.put("maxIdle", environment.getRequiredProperty(PROPERTY_NAME_POOL_MAX_IDLE));

        BasicDataSource bds = null;
        try {
            bds = BasicDataSourceFactory.createDataSource(props);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return bds;

    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor()
    {
        PersistenceExceptionTranslationPostProcessor b = new PersistenceExceptionTranslationPostProcessor();

        return b;
    }   

    @Bean 
    public HibernateExceptionTranslator hibernateExceptionTranslator(){ 
      return new HibernateExceptionTranslator(); 
    }

    @Bean
    public PlatformTransactionManager transactionManager() throws ClassNotFoundException {

        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_DAL_CLASSES_PACKAGE));
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);

        Properties jpaProperties = new Properties();
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
        jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));

        entityManagerFactoryBean.setJpaProperties(jpaProperties);

        return entityManagerFactoryBean;
    }
}

这是我的存储库界面

package my.dal.repository;

import my.domain.dal.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;


@Repository
public interface IUserRepository extends CrudRepository<User, String>{

}

这是UserService Service类,我必须在其中实现“richieExists”查询方法

package my.dal.service;

import my.dal.repository.IUserRepository;
import my.domain.dal.QUser;
import my.domain.dal.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.mysema.query.jpa.hibernate.HibernateQuery;


@Service
public class UserService {

    @Autowired
    private IUserRepository repository;

    public User find(String username) throws DataRetrievalFailureException
    {
        User user = null;

        user= repository.findOne(username);

        if (user == null)
            throw new DataRetrievalFailureException("User with username = \"" + username + "\" not found");
        else
            return user;
    }

    public User insert(User user) throws DuplicateKeyException
    {
        if (repository.findOne(user.getUsername()) != null)
            throw new DuplicateKeyException("User with username = \"" + user.getUsername() + "\" already exists");
        return repository.save(user);
    }

    public void delete(String username) throws DataRetrievalFailureException
    {
        if (repository.findOne(username) == null)
            throw new DataRetrievalFailureException("User with username =\"" + username + "\" not found");      
        repository.delete(username);
    }


    public User update(User user) throws DataRetrievalFailureException 
    {
        if (repository.findOne(user.getUsername()) == null)
            throw new DataRetrievalFailureException("User with username = \"" + user.getUsername() + "\" not found");        
        return repository.save(user);  

    }


    public boolean richieExists()
    {
        QUser qUser = QUser.user;       
        HibernateQuery query = new HibernateQuery(session); // I need a session instance here!
        User richie = query.from(qUser).where(qUser.username.eq("richie")).uniqueResult(qUser);
        return (richie!=null);
    }
}

谢谢

1 个答案:

答案 0 :(得分:1)

我这样解决了:

  1. 通过适当的注释从持久化上下文中获取当前的EntityManager

    @PersistenceContext

    EntityManager em;

  2. 接下来我使用了JPAQuery类(而不是HibernateQuery)来构建查询

    JPQLQuery query = new JPAQuery(em); //现在只使用查询对象

  3. 希望这个帮助