在插入之前,你想通过一段 SQL 为你的 POJO 某一个字段设值。你可以通过 @Prev 属性
@Table("t_pet") public class Pet{ @Name private String name; @Column("photo") @Prev( @SQL("SELECT txt FROM t_pet_photo WHERE pname=@name") ) private String photoPath; ...
@Prev 注解接受一组 @SQL 作为参数,它遵守如下约定:
此外,@Prev 也支持传入 EL 表达式,详情请查看 @EL 的 javadoc
@Prev(els=@EL("$me.genID()")) private String id; public String genID(){ return org.nutz.lang.random.R.UU16(); }
在插入之后,你想通过一段 SQL 为你的 POJO 某一个字段设值。你可以通过 @Next 属性
@Table("t_pet") public class Pet{ @Id @Next( @SQL("SELECT currval('t_pet_id_seq')") ) private long id; ...
如上例,执行插入后,你的 Pet 对象的 id 会被数据库中新的值更新。
@Next 的规则和 @Prev 是一样的
下面让我们举两个例子,详细说明一下 变量 和 参数 的异同点。
@Prev(@SQL("SELECT pet_name FROM t_user_pet WHERE ownm='$ownerName'")) private String name;
在执行 dao.inert 操作时, Nutz.Dao 会预先执行这段 SQL, 执行之前,变量 $ownerName 会被对象本身的 ownerName 字段的值替换,如果对象本身的 ownerName 字段的值恰好是 "zzh",那么执行的 SQL 会变成:
SELECT pet_name FROM m_user_pet WHERE ownm='zzh';
这段 SQL 执行的结果会复制给对象的 name 字段。
@Prev(@SQL("SELECT pet_name FROM t_user_pet WHERE ownm=@ownerName")) private String name;
在执行 dao.inert 操作时, Nutz.Dao 会预先执行这段 SQL, 执行之前,参数 @ownerName 会被 '?' 替换,并根据这段 SQL 生成 PreparedStatement 对象:
SELECT pet_name FROM m_user_pet WHERE ownm=?;
然后,根据对象本身的 ownerName 字段的值,为这个 PreparedStatement 设置参数,执行之后,这段 SQL 执行的结果会复制给对象的 name 字段。
无论是 @Prev 还是 @Next,你都是通过 @SQL 声明的数据库方言。但是,假设你并不确定你的 POJO 将会工作在哪一个数据库上,比如你的项目有两个数据源,一个是 Oracle 一个是 Postgresql,那么你的 POJO 该如何写方言呢?
@Table("t_pet") public class Pet{ @Id @Next({ @SQL(db = DB.PSQL, value="SELECT currval('t_pet_id_seq')"), @SQL(db = DB.ORACLE, value="SELECT t_pet_id_seq.currval FROM dual"), @SQL(db = DB.OTHER, value="SELECT MAX(id) FROM t_pet") }) private long id; ...
现在 Nutz.Dao 支持这些数据库. 其他未能识别的数据库将当成MySQL:
public enum DB { H2, DB2, PSQL, ORACLE, SQLSERVER, MYSQL, OTHER ... }
特别说一下Oracle的seq, 不过,更推荐使用触发器模拟自增.
@Table("t_pet") public class Pet{ @Id(auto=false) @Prev({ @SQL(db = DB.ORACLE, "SELECT t_pet_id_seq.nextval FROM dual") }) private long id; ...