我有一个类型为javax.persistence.Query的对象,其中有一个原生的PL / SQL查询(对于Oracle),如:
BEGIN
merge into account t
using dual
ON (t.account_id = '1')
WHEN MATCHED THEN
update set name=?, updated_date=? where account_id=?
WHEN NOT MATCHED THEN
insert (name, account_id, created_date) values (?, ?, ?);
COMMIT;
END;
我还有一个上面的位置参数列表,如下所示: 'some-name','01 / 01/2013 00:00:00','1'
问题是我想用sysdate替换updated_date / created_date的参数,以便我的最终go-to-DB查询如下所示:
BEGIN
merge into account t
using dual
ON (t.account_id = '1')
WHEN MATCHED THEN
update set name=?, updated_date=sysdate where account_id=?
WHEN NOT MATCHED THEN
insert (name, account_id, created_date) values (?, sysdate, ?);
COMMIT;
END;
但是,如果我将其中一个位置参数指定为'sysdate',那么Hibernate将字面上的字符串视为字符串,我会收到错误。 我怎么告诉Hibernate我想指定关键字sysdate而不是字符串'sysdate'?
由于某种原因,我们无法使用触发器或JVM日期(为简单起见省略了详细信息)
//在Martin的回复后更新
嗨,马丁,谢谢你的回答。
我看到你建议的代码,但无法做出任何改变。 很可能有一些我遗失的小作品,如果你可以帮助我的话会很棒。 我将发布相关的代码部分,以显示我所看到的内容。
public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID>
{
public static final PostgresUUIDType INSTANCE = new PostgresUUIDType();
public PostgresUUIDType() {
super( PostgresUUIDSqlTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE );
}
}
// which calls
public AbstractSingleColumnStandardBasicType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor<T> javaTypeDescriptor) {
super( sqlTypeDescriptor, javaTypeDescriptor );
}
// which calls
public AbstractStandardBasicType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor<T> javaTypeDescriptor) {
this.sqlTypeDescriptor = sqlTypeDescriptor;
this.javaTypeDescriptor = javaTypeDescriptor;
}
// And the BasicTypeRegistry looks like this:
class BasicTypeRegistry {
public BasicTypeRegistry() {
register( BooleanType.INSTANCE );
register( NumericBooleanType.INSTANCE );
register( TrueFalseType.INSTANCE );
...
}
void register(BasicType type) {
for ( String key : type.getRegistrationKeys() ) {
final Type old = registry.put( key, type );
}
}
}
你能帮我把日期联系起来吗? 非常感谢你的帮助!!
答案 0 :(得分:0)
要控制hibernate理解给定参数对象的方式,它使用BasicTypeRegistry。看看这个类:org.hibernate.type.PostgresUUIDType
它增加了对特殊postgres类型的支持。您甚至可以通过查看org.hibernate.type.BasicTypeRegistry
的构造函数来查找基本类型的更多示例。它包含hibernate映射的所有BasicType。
通过创建自己的BasicType并使用关键字的自定义对象表示,如Sysdate甚至新的OracleKeyword(“sysdate”)作为查询的参数,Hibernate将使用您的BasicType实现将其映射到SQL。所以现在你的BasicType实现让你完全控制最终结果(SQL)的样子。
请注意,在创建会话工厂configuration.getTypeResolver().registerTypeOverride(...)
之前,您需要将基本类型添加到类型解析程序。
<强>更新强>:
您的想法是,使用BasicType,您可以指定直接写出的实际SQL文本。它有点像黑客,因为这个值实际上是你写的东西。
关键部分是:
public static class PostgresUUIDSqlTypeDescriptor implements SqlTypeDescriptor {
public static final PostgresUUIDSqlTypeDescriptor INSTANCE = new PostgresUUIDSqlTypeDescriptor();
public int getSqlType() {
// ugh
return Types.OTHER;
}
请参阅Types.OTHER。在getBinder方法中,您可以直接控制SQL。可悲的是,我只记得这是我们几年前去过的方式。所以我试着概括一下 - 要注意,为了找到这个有用的你可以添加一些额外的研究:
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
st.setObject( index, javaTypeDescriptor.unwrap( value, UUID.class, options ), getSqlType() );
}
};
}
这是getBinder方法。在这里,您可以看到类型提供的基本绑定器的doBind方法。在doBind方法中,您将获得预准备语句,X是您映射的值,int是您的参数值应该应用于的索引。
此时您还可以控制设置参数的内容和方式。如果我是正确的,您可以引用基础数据库的关键字或函数作为参数值。因此,使用这种方式,您现在可以回退到jdbc并测试是否可以将sysdate指定为参数值。因此,如果你在JDBC中使用它,你可以使用基本类型来使用hibernate。
答案 1 :(得分:0)
在这里,我找到了一种更好的方法来做你想做的事。使用EnhancedUserType,您可以控制写入的实际SQL以直接表示对象。查看objectToSQLString方法。
只需在此方法中返回“sysdate”,您的问题就应该解决了。为此编写简单的用户类型也非常简单。查看一些hibernate的示例用户类型,并搜索google以获取其他示例。
这是EnhancedUserType接口的原始代码,包括一些注释。
package org.hibernate.usertype;
public interface EnhancedUserType extends UserType {
/**
* Return an SQL literal representation of the value
*/
public String objectToSQLString(Object value);
/**
* Return a string representation of this value, as it
* should appear in an XML document
*/
public String toXMLString(Object value);
/**
* Parse a string representation of this value, as it
* appears in an XML document
*/
public Object fromXMLString(String xmlValue);
}
答案 2 :(得分:0)
我终于使用了@ColumnTransformer(write =“”),除了非常简单易用外,它的效果非常好。
它可以帮助您为每次hibernate执行插入或更新查询时插入到最终查询中的列选择一个写表达式。