PreparedStatement,hibernate查询oracle char类型解决方案

有UserType的代码

参考:

http://blog.csdn.net/zhanngle/article/details/4188423

http://blog.csdn.net/daryl715/article/details/1927502

Oracle中执行以下sql

create table A (
id char(5)
);
insert into A values('11');

使用以下 Java 代码查询该记录

String sql="select * from A where id=?";
pstm=conn.prepareStatement(sql);
pstm.setString(1,"11");
rs=pstm.executeQuery();
System.out.println(rs.next());

呵呵...是不是查不到任何东西啊,将sql改掉看看:

String sql="select * from A where trim(id)=?";
是不是查出来了,哈!,可是能不能不用trim()就能查出来呢?
那是可以的!
请看代码:

String sql="select * from A where id=?";
pstm=conn.prepareStatement(sql);
((OraclePreparedStatement)pstm).setFixedCHAR(1, "11");
rs=ps.executeQuery();
System.out.println(rs.next());


执行看看,查询成功!
这是为什么呢,由于我英文水平不好,所以请打开以下链接看看!
http://forums.oracle.com/forums/thread.jspa;jsessionid=8d92200630de527b2f61c7ef4d3296318c855aa88fe1.e34Tb34Lb34PbO0Lb3eTahiPbNyTe0?messageID=504702

对于hibernate查询oracle char类型可谓是遇到大麻烦了,因为hibernate内部使用的是PrepareStatement,在查询oracle char类型时会出现上述的问题,我的解决方案是定义一个UserType,该UserType对字段值自动补齐空格,以下是我的主键示例:

@Id
@GeneratedValue(generator = "id")
@GenericGenerator(name = "id", strategy = "uuid")
@Type(parameters = {}, type = "test.OracleCharType")
private String id;

test.OracleCharType就是我自定义的UserType类,它实现了当我们传进来的id值少于5位时,自动加空格,使id值满足5位.
这样,当我们使用以下语句获取对象,便能获取到了.

session.get(A.class,"11")

它底层的查询语句会转换成

select * from A where id='11   ';

怎么样,明白了不.你可能会说为什么使用加空格而不使用trim()函数截取的方式,那是因为hibernate的UserType只能对字段值做手脚(如:'11'变成了'11   ').
这种方案只需要定义一个UserType,然后在hbm文件里配制一下就可使用了.
当然这只是其中一种解决方案,如果你不嫌麻烦的话,可以将查询都改成hql+trim()的方式查询,那么工作量会加很多.
也可以为每个po对象加一个<sql-query></sql-query>,不过这种方式到没有试过,不知是否可行!


附:

基于hibernate 4.1.9 的UserType 实现类 OracleCharType

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;

public class OracleCharType implements UserType{
	
	private int length = 32;

	@Override
	public int[] sqlTypes() {
		return new int[]{Types.CHAR};
	}

	@Override
	public Class returnedClass() {
		return String.class;
	}

	@Override
	public boolean equals(Object x, Object y) throws HibernateException {
		if (x == y)
            return true;
        if (x == null || y == null)
            return false;
        
        if (x instanceof String && y instanceof String)
        	return x.equals(y);
        
		return false;
	}

	@Override
	public int hashCode(Object x) throws HibernateException {
		
		if (x instanceof Character) {
			return ((Character)x).hashCode();
		}
		
		return 0;
	}

	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
			throws HibernateException, SQLException {
		return rs.getString(names[0]);
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
			throws HibernateException, SQLException {
		
		StringBuffer v = new StringBuffer((String) value);
		
		if (v.length() < length) {
			int count = length - v.length();
			for (int i = 0; i < count; i++) {
				v.append(" ");
			}
		}
		
		st.setString(index, v.toString());
	}

	@Override
	public Object deepCopy(Object value) throws HibernateException {
		return value;
	}

	@Override
	public boolean isMutable() {
		return false;
	}

	@Override
	public Serializable disassemble(Object value) throws HibernateException {
		return null;
	}

	@Override
	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		return null;
	}

	@Override
	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		return null;
	}

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值