最近在用jfianl做一个手机端的后台,jfinal不用多说,非常简单而且好用,比struct这个框架简单多了,配置c3p0连接池,配置oracle数据库等都很简单.
但是封装了,如果我想在oracle数据库insert中初始化一个bold字段,我要用到EMPTY_BLOB()这个函数来初始化该怎么办呢,如果直接在set方法中当字符串
放进去肯定是不行的,会当做字符串处理的。
StringBuilder sql=new StringBuilder();
sql.append("insert into TUSERANSWER(type,userid,answer,isping,correct,time,pic) ");
sql.append("values(?,?,?,?,?,?,EMPTY_BLOB())");
在此之前,我们先看一下jfianl数据库插入save的原理
在jfinal中,操作数据库都进行了封装。Model 是 ActiveRecord 中最重要的组件之一,它是 MVC 模式中的 Model 部分。
引用原本的帮助文档说明:
基于 ActiveRecord的 Model 无需定义属性,无需定义 getter、setter 方法,无需 XML 配置,无需 Annotation 配置,
极大降低了代码量。
public class User extends Model<User> {
public static final User dao = new User();
}
方式1:
其中数据库的insert语句可以这样写:
// 创建name属性为James,age属性为25的User对象并添加到数据库
new User().set("name", "James").set("age", 25).save();
方式2::
JFinal 独创 Db + Record 模式
// 创建name属性为James,age属性为25的record对象并添加到数据库
Record user = new Record().set("name", "James").set("age", 25);
Db.save("user", user);
上面都是jfinal的数据库insert的封装,完全不用自己写insert语句,也不用hibenate那样的应声
/**
* Save model.
*/
public boolean save() {
Config config = getConfig();
Table table = getTable();
StringBuilder sql = new StringBuilder();
List<Object> paras = new ArrayList<Object>();
config.dialect.forModelSave(table, attrs, sql, paras);
// if (paras.size() == 0) return false; // The sql "insert into tableName() values()" works fine, so delete this line
// --------
Connection conn = null;
PreparedStatement pst = null;
int result = 0;
try {
conn = config.getConnection();
if (config.dialect.isOracle())
pst = conn.prepareStatement(sql.toString(), new String[]{table.getPrimaryKey()});
else
pst = conn.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
config.dialect.fillStatement(pst, paras);
result = pst.executeUpdate();
getGeneratedKey(pst, table);
getModifyFlag().clear();
return result >= 1;
} catch (Exception e) {
throw new ActiveRecordException(e);
} finally {
config.close(pst, conn);
}
}
从源码不难发现,这里就是java的jdbc。可以看到它的sql。那么我们再找一下sql是如何生成的。
config.dialect.forModelSave(table, attrs, sql, paras);
上面这句就是sql生成过的主要,再看一下forModelSave这个方法:
public void forModelSave(Table table, Map<String, Object> attrs, StringBuilder sql, List<Object> paras) {
sql.append("insert into `").append(table.getName()).append("`(");
StringBuilder temp = new StringBuilder(") values(");
for (Entry<String, Object> e: attrs.entrySet()) {
String colName = e.getKey();
if (table.hasColumnLabel(colName)) {
if (paras.size() > 0) {
sql.append(", ");
temp.append(", ");
}
sql.append("`").append(colName).append("`");
temp.append("?");
paras.add(e.getValue());
}
}
sql.append(temp.toString()).append(")");
}
哈哈,看到上面可以知道它sql的生成。只要拿到这个
Connection对象,什么语句插入都没有问题了。关键就在这里
重点来了,我们是继承Model这个类来的,我们要定义自己的插入语句,也必须用到Model这个类,在这个类的基础上添加自己的insert语句。
这个Model添加了自己的insert方法,sql语句和参数都是自己传递进来,虽然自己写sql语句,但是可以自由控制了
package biden.com.ririfen.model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import biden.com.ririfen.entity.CorrectType;
import biden.com.ririfen.entity.PingType;
import com.jfinal.plugin.activerecord.ActiveRecordException;
import com.jfinal.plugin.activerecord.Config;
import com.jfinal.plugin.activerecord.DbKit;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
/**
*
* @author Administrator
*
*/
public class TUSERANSWER extends Model<TUSERANSWER>{
private static final long serialVersionUID = -8387370485055880497L;
public static final TUSERANSWER dao = new TUSERANSWER();
/**
* 插入
*
*/
public boolean insert(String sql,Object[] params){
if(params.length!=6){
throw new ParamNotFindException("参数错误(自定义异常抛出)");
}
Config config = getConfig();
Connection conn = null;
PreparedStatement pst = null;
int result = 0;
try {
conn = config.getConnection();
pst = conn.prepareStatement(sql);
pst.setString(1,(String)params[0]);//type
pst.setLong(2,Long.valueOf(params[1].toString()));//userid
pst.setString(3,params[2].toString());//answer
pst.setString(4,params[3].toString());//isping
pst.setString(5,params[4].toString());//correct
pst.setTimestamp(6,(Timestamp)params[5]);//time
result = pst.executeUpdate();
return result >= 1;
} catch (Exception e) {
throw new ActiveRecordException(e);
} finally {
config.close(pst, conn);
}
}
private Config getConfig() {
return DbKit.getConfig(getClass());
}
/**
* 自定义异常
* 说明:参数错误时候抛出该异常
* @author Administrator
*
*/
public class ParamNotFindException extends RuntimeException {
private static final long serialVersionUID = 6414324487047290159L;
public ParamNotFindException(String message) {
super(message);
}
public ParamNotFindException(Throwable cause) {
super(cause);
}
public ParamNotFindException(String message, Throwable cause) {
super(message, cause);
}
}
}
下面是调用上面方法的例子,可以看出,我门可以用oracle函数了。
<span style="white-space:pre"> </span>StringBuilder sql=new StringBuilder();
sql.append("insert into TUSERANSWER(type,userid,answer,isping,correct,time,pic) ");
sql.append("values(?,?,?,?,?,?,EMPTY_BLOB())");
Object[] params = {
type_1.toString(),
id,
an,
PingType.none.toString(),
CorrectType.none.toString(),
new Timestamp(System.currentTimeMillis()),
};
boolean b1 = tanswer.insert(sql.toString(), params);
在这里记录一下,分享给大家,有什么错误可以提出。