关于Hibernate3的escape解决方法

本文介绍了一种在不使用全文索引的情况下,通过转义特殊字符实现精确模糊查询的方法。针对用户输入中的通配符,如*和?,文章详细解释了如何在SQL查询中正确使用这些符号,并提供了具体实现代码。
不知道大家有没有碰到,还是没有这种需求。就是用like来查询,我们没有用Lucene,Compass这种全文索引的方案,我们只是简单的添加%进行like查询。用户搜索的时候就使用*和?来代表任意和一个。所以要对"%"和"_"进行转义,我们使用的是oracle数据库。sql语句看起来可能是这样的。
SELECT   *   FROM  t_user  where  nickname  like   ' %Goo\_D '   escape   ' \ '
这里对_进行转义了。因为用户昵称包含下划线,如果不进行转义就表示一个任意字符。有时候我们可能还需要对%进行转义。同样的方法在%前加\% 但是比起普通的like语句。多了一个声明转义符的语句。所以我们会想到这样的语句
DetachedCriteria criteria  =  DetachedCriteria.forClass(User. class );
criteria.add(Restrictions.like(
" nickname " , user.getNickname() + " ' escape'\ " ));
但是这样是不管用的。
接下来可能会想到使用Hibernate3的原生sql查询,其实我们不需要这样做。我们还是使用Criteria条件查询。
criteria.add(Restrictions.sqlRestriction( " {alias}.nickname like ? escape'/' " , StringUtil.escapeSQLLike(user.getNickname()), Hibernate.STRING));
这样Hibernate产生的语句就是我们想要的语句了。
     /**
     * 转义like语句中的
     * <code>'_'</code><code>'%'</code>
     * 将<code>'?'</code>转成sql的<code>'/_'</code>
     * 将<code>'%'</code>转成sql的<code>'/%'</code>
     * <p>
     *   例如搜索<code>?aa*bb?c_d%f</code>将转化成<br/>
     *   <code>_aa%bb_c/_d/%f</code>
     * </p>
     * 
@param  likeStr
     * 
@return
     * 
@author  <a href=" http://jdkcn.com ">somebody</a>
     
*/
    
public   static  String escapeSQLLike(String likeStr) {
        String str 
=  StringUtils.replace(likeStr,  " _ " " /_ " );
        str 
=  StringUtils.replace(str,  " % " ,     " /% " );
        str 
=  StringUtils.replace(str,  " ? " " _ " );
        str 
=  StringUtils.replace(str,  " * " " % " );
        
return  str;
    }

创造共用协议:署名,非商业,保持一致   除经特别注明外,本文章版权归 莫多泡泡所有.
署名,非商业用途,保持一致.    somebody(莫多) 75503.html

莫多 2006-10-16 23:29 发表评论
package com.aiearth.drone.config; import com.aiearth.drone.security.DataSource.UmspscDataSource; import org.springframework.aop.Advisor; import org.springframework.aop.aspectj.AspectJExpressionPointcut; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.interceptor.*; import javax.sql.DataSource; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; @Configuration @EnableTransactionManagement @ComponentScan(basePackages = {"com.aiearth.drone.dao", "com.aiearth.pojo", "com.aiearth.drone.service"}) // 根据需要调整扫描路径 public class HibernatePostgisConfig { @Autowired private Environment env; @Bean(name = "entityManagerFactory") @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactory() { System.setProperty("hibernate.query.escape_like_parameter", "false"); LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); // 扫描实体类路径(与Hibernate的packagesToScan一致) em.setPackagesToScan("com.aiearth.pojo"); em.setDataSource(dataSource()); // 使用Hibernate作为JPA实现 HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); // 配置JPA属性(复用Hibernate的方言等配置) Properties properties = new Properties(); // properties.setProperty("hibernate.dialect", "org.hibernate.spatial.dialect.postgis.PostgisPG10Dialect"); properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); properties.setProperty("hibernate.show_sql", "true"); properties.setProperty("hibernate.query.sql.escape-identifier", "false"); properties.setProperty("hibernate.format_sql", "false"); properties.setProperty("hibernate.use_sql_comments", "false"); properties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); em.setJpaProperties(properties); return em; } // 数据源配置 @Bean(name = "dataSource") public DataSource dataSource() { UmspscDataSource dataSource = new UmspscDataSource(); dataSource.setDriverClassName("org.postgresql.Driver"); dataSource.setJdbcUrl(env.getProperty("drone.jdbc.url") + "?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&stringtype=unspecified"); dataSource.setUsername(env.getProperty("drone.jdbc.username")); dataSource.setPassword(env.getProperty("drone.jdbc.password")); dataSource.setConnectionTimeout(30000); dataSource.setIdleTimeout(180000); dataSource.setMaximumPoolSize(30); dataSource.setMinimumIdle(10); dataSource.setMaxLifetime(1200000); dataSource.setConnectionTestQuery("SELECT 1"); // 添加日志输出 System.out.println("DataSource configured with URL: " + dataSource.getJdbcUrl()); System.out.println("Username: " + dataSource.getUsername()); return dataSource; } // SessionFactory 配置 @Bean(name = "sessionFactory") // @Primary public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); sessionFactory.setPackagesToScan("com.aiearth.drone.dao", "com.aiearth.pojo"); Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.query.sql.escape-identifier", "false"); // hibernateProperties.setProperty("hibernate.show_sql", "false"); // hibernateProperties.setProperty("hibernate.format_sql", "false"); // hibernateProperties.setProperty("hibernate.use_sql_comments", "false"); // hibernateProperties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); sessionFactory.setHibernateProperties(hibernateProperties); return sessionFactory; } // 事务管理器配置 @Bean(name = "transactionManager") @Primary public PlatformTransactionManager transactionManager() { HibernateTransactionManager txManager = new HibernateTransactionManager(); txManager.setSessionFactory(sessionFactory().getObject()); return txManager; } // 事务通知配置 @Bean public TransactionInterceptor txAdvice() { NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute(); readOnlyTx.setReadOnly(true); readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(); requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class))); requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); Map<String, TransactionAttribute> txMap = new HashMap<>(); txMap.put("get*", readOnlyTx); txMap.put("count*", readOnlyTx); txMap.put("find*", readOnlyTx); txMap.put("list*", readOnlyTx); txMap.put("*", requiredTx); source.setNameMap(txMap); TransactionInterceptor txAdvice = new TransactionInterceptor(); txAdvice.setTransactionManager(transactionManager()); txAdvice.setTransactionAttributeSource(source); return txAdvice; } // AOP 配置 @Bean public Advisor txAdviceAdvisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression("execution(* com.aiearth..*.service..*Service.*(..))"); return new DefaultPointcutAdvisor(pointcut, txAdvice()); } // 如果需要,可以添加其他 Bean 配置,例如 PropertySourcesPlaceholderConfigurer /* @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }*/ } 我这样配在bean里对吗,我这样设置并没有生效
07-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值