Jbomo框架系列教程(三)-ORM 有更新!
第三章:ORM
ORM主要功能也是fork至jfinal1.9版本,在原来的基础上做改进。
简单示例
- 配置数据源
除了上述例子中的配置外,添加一组数据源配置
jbomo.devMode = true
jbomo.server.port = 8083
jbomo.server.host = localhost
jbomo.datasource.url =jdbc:mysql://192.168.2.169/jbomo-example?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
jbomo.datasource.user = admin_union
jbomo.datasource.password =gM_v9og51Pn_BRcT2d8R
示例中的建表语句
CREATE TABLE `t_person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(5) DEFAULT NULL,
`addtime` char(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
- Person实体类
通常情况下,实体类并不需要任何编码,只需要继承Model
public class Person extends Model<Person> {
}
- PersonService服务类
PersonService需要继承通用服务类Service
public class PersonService extends Service<Person> {
public List<Person> findByAge(int age) {
String sql = "select * from " + table.getName() + " where age = ? order by addtime";
List<Person> persons = dao.find(sql, age);
return persons;
}
}
- Module配置类
如上述配置类示例,下面配置了 t_person
表与Person实体类的映射关系,没有指定数据源时,默认使用应用缺省数据源,也就是main数据源。
public class Example03Module extends DaoModule {
@Override
public void configTable(Tables tables) {
tables.add("t_person", Person.class);
}
}
- 业务测试类
public class Example03Appliaction {
public static void main(String[] args) {
Jbomo.run();
doPersonTest();
}
private static void doPersonTest() {
Person person = new Person();
person.set("name","李四").set("age",18).set("addtime", DateUtil.getCurDateTimeStr());
PersonService personService = new PersonService();
// 保存person对象
personService.save(person);
// 根据ID加载Person对象
Person person1 = personService.findById(1);
System.out.println(person1.toJson());
// 根据年龄获取Person列表
personService.findByAge(18).stream().forEach(p -> {
System.out.println(p.toJson());
});
}
}
{"addtime":"2019-01-18 13:56:12","name":"张三","id":1,"age":18}
{"addtime":"2019-01-18 13:56:12","name":"张三","id":1,"age":18}
{"addtime":"2019-01-18 14:05:54","name":"李四","id":2,"age":18}
{"addtime":"2019-01-18 14:11:04","name":"李四","id":3,"age":18}
{"addtime":"2019-01-18 14:58:57","name":"李四","id":4,"age":18}
- 示例代码工程目录图
数据源配置说明
Jbomo支持多数据源配置,如下配置所示,没有指定数据源名称的为系统缺省数据源(main)。所以在配置其它非主数据源的时候应该避开“main”数据源名称。
jbomo.datasource.url = ${jbomo.mysql.jdbcUrl}
jbomo.datasource.user = ${jbomo.mysql.user}
jbomo.datasource.password =${jbomo.mysql.password}
jbomo.datasource.sharding.url = ${jbomo.datasource.sharding.url}
jbomo.datasource.sharding.user = ${jbomo.datasource.sharding.user}
jbomo.datasource.sharding.password =${jbomo.datasource.sharding.password}
jbomo.datasource.visitcnt.url = ${jbomo.datasource.visitcnt.url}
jbomo.datasource.visitcnt.user = ${jbomo.datasource.visitcnt.user}
jbomo.datasource.visitcnt.password = ${jbomo.datasource.visitcnt.password}
数据源的配置项说明:
配置项 | 说明 |
---|---|
driverClass | 数据库驱动类,默认(“com.mysql.jdbc.Driver”) |
maxPoolSize | 连接池最大连接数,默认(100) |
minPoolSize | 连接池最新连接数,默认(10) |
initialPoolSize | 初始化连接数,默认(10) |
factory | 连接池实现方式(c3p0,druid,hikari等,暂时只实现c3p0) |
partitionEnable | 是否需要分库分表 |
partitionDatasources | 分库时候逻辑数据源使用,指定分库物理数据源,多个数据源用逗号“,”隔开 |
当业务需要对数据进行分库时,数据源还分为逻辑数据源和物理数据源,逻辑数据源只需要配置partitionEnable为ture以及指定几个分库物理数据源partitionDatasources。如下示例:
jbomo.datasource.pes.partitionEnable=true
jbomo.datasource.pes.partitionDatasources=p1,p2,p3
jbomo.datasource.p1.url = ${jbomo.datasource.p1.url}
jbomo.datasource.p1.user = ${jbomo.datasource.p1.user}
jbomo.datasource.p1.password = ${jbomo.datasource.p1.password}
jbomo.datasource.p1.partitionEnable = true
jbomo.datasource.p2.url = ${jbomo.datasource.p1.url}
jbomo.datasource.p2.user = ${jbomo.datasource.p1.user}
jbomo.datasource.p2.password = ${jbomo.datasource.p1.password}
jbomo.datasource.p2.partitionEnable = true
jbomo.datasource.p3.url = ${jbomo.datasource.p1.url}
jbomo.datasource.p3.user = ${jbomo.datasource.p1.user}
jbomo.datasource.p3.password = ${jbomo.datasource.p1.password}
jbomo.datasource.p3.partitionEnable = true
dao&Model
Model
dao是Service示例中的一个Model
的实例化对象,这边的dao不能当做一个model实体进行save或者delete操作。
Service示例:
public class PersonService extends Service<Person> {
public List<Person> findByAge(int age) {
String sql = "select * from " + table.getName() + " where age = ? order by addtime";
List<Person> persons = dao.find(sql, age);
return persons;
}
}
注意Service
必须指定泛型中具体Model类名。
Model的其它用法如下:
// 删除值为2的Person
dao.deleteById(2);
// 加载id为3的Person对象
Person person = dao.findById(3);
// 获取person的名称
String name = person.getStr("name");
// 获取person的年龄
int age = person.getInt("age");
// 更新person,建议这样使用
update(person.set("age",20));
// 不建议这样使用,因为该使用方式不适应于rpc远程服务调用
person.set("age",21).update();
// 分页查询
dao.paginate(1,10,"select * "," from "+table.getName());
// 关联查询示例
String sql = "select b.*, u.user_name from blog b inner join user u on b.user_id=u.id where b.id=?";
Blog blog = dao.findFirst(sql, 123);
String name = blog.getStr("user_name");
Model注意事项
1.model.set()与model.put()
model.set()会根据model的表字段校验是否包含该属性,如果model映射的表不存在该属性字段会抛出ActiveRecordException异常。
model.put()不会校验是否存在该属性,仅当做hashmap键值对存储。
2.model实体复制
model.setAttrs(model2);
当实体数据存储在一个hashmap中的时候,可以使用如下方式拷贝属性:
//可以使用setAttrs拷贝,当不存在字段时候会抛异常
model.setAttrs(hashMap);
//可以使用hasColumnLabel判断是否存在字段
hashMap.forEach((k,v)->{
if (model.getTable().hasColumnLabel(k)){
model.set(k,v);
}
});
Db + Record模式
Db 类及其配套的 Record 类,提供了在 Model 类之外更为丰富的数据库操作功能。使用Db 与Record 类时,无需对数据库表进行映射,Record 相当于一个通用的 Model。以下为Db + Record 模式的一些常见用法:
// 创建name属性为James,age属性为25的record对象并添加到数据库
Record user = new Record().set("name", "James").set("age", 25);
Db.save("user", user);
// 删除id值为25的user表中的记录
Db.deleteById("user", 25);
// 查询id值为25的Record将其name属性改为James并更新到数据库
user = Db.findById("user", 25).set("name", "James");
Db.update("user", user);
// 查询id值为25的user, 且仅仅取name与age两个字段的值
user = Db.findById("user", 25, "name, age");
// 获取user的name属性
String userName = user.getStr("name");
// 获取user的age属性
Integer userAge = user.getInt("age");
// 查询所有年龄大于18岁的user
List<Record> users = Db.find("select * from user where age > 18");
// 分页查询年龄大于18的user,当前页号为1,每页10个user
Page<Record> userPage = Db.paginate(1, 10, "select *", "from user where age > ?", 18);
事务处理
以下为事务处理示例:
boolean succeed = Db.tx(new IAtom(){
public boolean run() throws SQLException {
int count = Db.update("update account set cash = cash - ? where id = ?", 100, 123);
int count2 = Db.update("update account set cash = cash + ? where id = ?", 100, 456);
return count == 1 && count2 == 1;
}});
以上两次数据库更新操作在一个事务中执行,如果执行过程中发生异常或者 invoke()方法返回 false,则自动回滚事务。
评论
发表评论
|
|