GORM或Hibernate查询或更新部分属性
若想查询一个POJO类的部分属性,如
@Entity
class Captcha {
String str
String bak
static constraints = {
bak(nullable: true)
}
}
若只想查询str,不查bak。可以通过HQL或Criteria指定要查询的字段。
如:
List<Object[]> list = Captcha.withCriteria {
projections {
property("id")
property("str")
property("version")
}
eq("id", 4L)
}
或
List<Object[]> list = Captcha.executeQuery("select id,str,version from Captcha")
注意这里返回的是对象数组,并非Domain对象。
如果要返回Domain对象也好办:
Captcha.executeQuery("select new Captcha(id,str,version) from Captcha"])
前提是Domain类必须有相应的构造函数:
Captcha(id, String str, version) {
this.id = id
this.str = str
this.version = version
}
Criteria应该也可以返回Domain对象,偶现在还没找到方法,欢迎补充。
Hibernate更新时默认更新该类的所有属性。若想save时只更新部分属性需要额外的方法。
dynamicUpdate属性可以做到这一点,它默认是false:系统启动时预先生成sql。置为true可在运行期动态生成sql。
static mapping = {
dynamicUpdate true
}
仅仅修改了该属性还不行,save时那些没有设置的字段:bak被置为null了。需要在设置属性值之前先锁定该对象,再修改,然后save。待事务提交之后自动解锁了。
Captcha o = new Captcha(id: 4, str: "dsd", version: 4)
Captcha.withTransaction {
o.lock() //先上锁
o.str += " modified " //再修改值
if (o.hasErrors() || !o.save(flush: true)) { //然后save
log.error(o.errors.toString())
}
} //事务提交后自动解锁了。
这样,持久化后数据库中bak字段仍是以前的值,没有被置为null。
检验下事务提交后是否自动解锁:
Captcha o = new Captcha(id: 4, str: "dsd", version: 4)
Captcha.withTransaction {
o.lock() //先上锁
o.str += " modified "
if (o.hasErrors() || !o.save(flush: true)) {
log.error(o.errors.toString())
}
}
Captcha.withTransaction {
o.str += " modified "// 未上锁
if (o.hasErrors() || !o.save(flush: true)) {
log.error(o.errors.toString())
}
}
这样,bak字段在第二次save时被置为null了,可以进入数据库验证一下。