ORM

    由于Jboot的数据库读取是依赖于JFinal,所以实际上只要是JFinal支持的数据库类型,Jboot都会支持,比如常用的数据库类型有:

    • Mysql
    • Oracle
    • SqlServer
    • postgresql
    • sqlite
    • 其他标准的数据库

    在Jboot应用连接数据库之前,我们需要在resources目录下创建一个jboot.properties配置文件,并在jboot.properties编写内容如下:

    其中:

    • jboot.datasource.type 是配置数据库类型
    • jboot.datasource.url 是数据库请求URL地址
    • jboot.datasource.user 是数据库需要的账号
    • jboot.datasource.password 是数据库需要的密码

    除了 ,urluserpassword四个配置以外,jbootdatasource 还支持以下配置:

    • jboot.datasource.name 数据源的名称
    • jboot.datasource.driverClassName 驱动类名
    • jboot.datasource.connectionInitSql 连接初始化Sql
    • jboot.datasource.poolName 线程池名称
    • jboot.datasource.cachePrepStmt 缓存启用
    • jboot.datasource.prepStmtCacheSize 缓存大小
    • jboot.datasource.prepStmtCacheSqlLimit 缓存限制
    • jboot.datasource.maximumPoolSize 线程池大小
    • jboot.datasource.sqlTemplatePath sql文件路径
    • jboot.datasource.sqlTemplate sql文件,多个用英文逗号隔开
    • jboot.datasource.table 该数据源对应的表名,多个表用英文逗号隔开

    更多的具体使用,特别是name、table等在分库分表章节会讲到。

    Model

    model是MVC设计模式中的M,但同时每个model也会对应一个数据库表,它充当 MVC 模式中的 Model 部分。以下是Model 定义示例代码:

    1. public class User extends JbootModel<User> {
    2. public static final User dao = new User().dao();
    3. }

    以上代码中的 User 通过继承 Model,便立即拥有的众多方便的操作数据库的方法。在 User中声明的 dao 静态对象是为了方便查询操作而定义的,该对象并不是必须的。同时,model无需定义 getter、setter 方法,无需 XML 配置,极大降低了代码量。

    以下是model常见的用法:

    1. // 创建name属性为James,age属性为25的User对象并添加到数据库
    2. new User().set("name", "James").set("age", 25).save();
    3. // 删除id值为25的User
    4. User.dao.deleteById(25);
    5. // 查询id值为25的User将其name属性改为James并更新到数据库
    6. User.dao.findById(25).set("name", "James").update();
    7. // 查询id值为25的user, 且仅仅取name与age两个字段的值
    8. User user = User.dao.findByIdLoadColumns(25, "name, age");
    9. // 获取user的name属性
    10. String userName = user.getStr("name");
    11. // 获取user的age属性
    12. Integer userAge = user.getInt("age");
    13. // 查询所有年龄大于18岁的user
    14. List<User> users = User.dao.find("select * from user where age>18");
    15. // 分页查询年龄大于18的user,当前页号为1,每页10个user
    16. Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user
    17. where age > ?", 18);

    注意:User 中定义的 public static final User dao 对象是全局共享的,只能 用于数据库查询,不能 用于数据承载对象。数据承载需要使用 new User().set(…)来实现。

    注解是给Model使用的,表示让Model映射到哪个数据库表,使用代码如下:

    1. @Table(tableName = "user", primaryKey = "id")
    2. public class User extends JbootModel <Company> {
    3. }

    值得注意的是:

    Db 类及其配套的 Record 类,提供了在 Model 类之外更为丰富的数据库操作功能。使用Db 与 Record 类时,无需对数据库表进行映射,Record 相当于一个通用的 Model。以下为 Db +Record 模式的一些常见用法:

    1. // 创建name属性为James,age属性为25的record对象并添加到数据库
    2. Record user = new Record().set("name", "James").set("age", 25);
    3. Db.save("user", user);
    4. // 删除id值为25的user表中的记录
    5. Db.deleteById("user", 25);
    6. // 查询id值为25的Record将其name属性改为James并更新到数据库
    7. user = Db.findById("user", 25).set("name", "James");
    8. Db.update("user", user);
    9. // 获取user的name属性
    10. String userName = user.getStr("name");
    11. // 获取user的age属性
    12. // 查询所有年龄大于18岁的user
    13. Page<Record> userPage = Db.paginate(1, 10, "select *", "from user where
    14. age > ?", 18);

    或者,事务操作:

    1. boolean succeed = Db.tx(new IAtom(){
    2. public boolean run() throws SQLException {
    3. int count = Db.update("update account set cash = cash - ? where
    4. id = ?", 100, 123);
    5. int count2 = Db.update("update account set cash = cash + ? where
    6. id = ?", 100, 456);
    7. return count == 1 && count2 == 1;
    8. }
    9. });

    以上两次数据库更新操作在一个事务中执行,如果执行过程中发生异常或者 run()方法返回 false,则自动回滚事务。

    更多

    请参考JFinal的文档:

    在Jboot中,使用多数据源非常简单。

    在以上章节里,我们知道,要连接数据库需要做如下配置:

    假设我们再增加两个数据源,只需要在jboot.properties文件在添加如下配置即可:

    1. jboot.datasource.a1.type=mysql
    2. jboot.datasource.a1.turl=jdbc:mysql://127.0.0.1:3306/jboot1
    3. jboot.datasource.a1.tuser=root
    4. jboot.datasource.a1.tpassword=your_password
    5. jboot.datasource.a2.type=mysql
    6. jboot.datasource.a2.turl=jdbc:mysql://127.0.0.1:3306/jboot2
    7. jboot.datasource.a2.tuser=root
    8. jboot.datasource.a2.tpassword=your_password

    这表示,我们又增加了数据源和数据源a2,在使用的时候,我们只需要做一下使用:

    1. Company company = new Company();
    2. company.setCid("1");
    3. company.setName("name");
    4. company.use("a1").save();

    company.use("a1").save();表示使用数据源a1进行保存。

    值得注意的是:

    在多数据源应用中,很多时候,我们一个Model只有对应一个数据源,而不是一个Model对应多个数据源。假设Company只有在a1数据源中存在,在其他数据源并不存在,我们需要把a1数据源的配置修改如下:

    1. jboot.datasource.a1.type=mysql
    2. jboot.datasource.a1.url=jdbc:mysql://127.0.0.1:3306/jboot1
    3. jboot.datasource.a1.user=root
    4. jboot.datasource.a1.password=your_password
    5. jboot.datasource.a1.table=company
    6. jboot.datasource.a2.type=mysql
    7. jboot.datasource.a2.url=jdbc:mysql://127.0.0.1:3306/jboot2
    8. jboot.datasource.a2.user=root
    9. jboot.datasource.a2.password=your_password
    10. jboot.datasource.a1.table=user,xxx(其他非company表)
    1. Company company = new Company();
    2. company.setCid("1");
    3. company.setName("name");
    4. //company.use("a1").save();
    5. company.save();

    代码中不再需要 use("a1") 指定数据源,因为company只有一个数据源。

    分库和分表

    在Jboot中,分表是通过sharding-jdbc( 网址: 来实现的,所以,在了解Jboot的分表之前,请先阅读了解sharding-jdbc的配置信息。

    分库分表相关demo: 点击这里

    分库意味你有多个数据库,每个数据库会对应一个数据源。

    例如,我们的应用有三个数据库,分别是 db1,db2,db3,那么需要我们在 jboot.properties 配置文件里配置上三个数据,配置如下:

    1. jboot.datasource.db1.url = jdbc:mysql://127.0.0.1:3306/db1
    2. jboot.datasource.db1.user = root
    3. jboot.datasource.db1.password =
    4. jboot.datasource.db2.url = jdbc:mysql://127.0.0.1:3306/db2
    5. jboot.datasource.db2.user = root
    6. jboot.datasource.db2.password =
    7. jboot.datasource.db3.url = jdbc:mysql://127.0.0.1:3306/db3
    8. jboot.datasource.db3.user = root
    9. jboot.datasource.db3.password =

    我们希望在分库的时候,通过Model的主键ID进行hashcode进行取模,决定分库。因此需要编写分库策略,代码如下:

    编写好分库策略后,需要给Model配置上分库策略:

    1. @Table(tableName = "tb_user",
    2. primaryKey = "id",
    3. // 具体的表tb_user${0..2} 表示有三张表 tb_user0,tb_user1,tb_user2,
    4. // main 是默认数据源的名称
    5. actualDataNodes = "main.tb_user${0..2}",
    6. //分表策略
    7. databaseShardingStrategyConfig = UserDatabaseShardingStrategyConfig.class
    8. )
    9. public class UserModel extends JbootModel<UserModel> {
    10. //geter setter
    11. }

    demos

    例如:有一个userModel,我们希望能进行分为三张表,通过id的hashcode进行取模,代码如下:

    1. @Table(tableName = "tb_user",
    2. primaryKey = "id",
    3. // 具体的表tb_user${0..2} 表示有三张表 tb_user0,tb_user1,tb_user2,
    4. // main 是默认数据源的名称
    5. actualDataNodes = "main.tb_user${0..2}",
    6. //分表策略
    7. )
    8. public class UserModel extends JbootModel<UserModel> {
    9. //geter setter
    10. }

    编写UserModel的分表策略 UserTableShardingStrategyConfig,代码如下:

    1. public class UserTableShardingStrategyConfig implements ShardingStrategyConfiguration {
    2. @Override
    3. public ShardingStrategy build() {
    4. return shardingStrategy;
    5. }
    6. private ShardingStrategy shardingStrategy = new ShardingStrategy() {
    7. @Override
    8. public Collection<String> getShardingColumns() {
    9. //根据id进行分表
    10. return Sets.newHashSet("id");
    11. }
    12. @Override
    13. public Collection<String> doSharding(Collection<String> availableTargetNames, Collection<ShardingValue> shardingValues) {
    14. ListShardingValue shardingValue = (ListShardingValue) shardingValues.stream().findFirst().get();
    15. String tableName = "tb_user" + Math.abs(shardingValue.getValues().iterator().next().toString().hashCode()) % 3;
    16. System.out.println("插入数据到表:" + tableName);
    17. //返回通过计算得到的表
    18. return Sets.newHashSet(tableName);
    19. }
    20. };
    21. }

    编写配置文件:

    1. jboot.datasource.type=mysql
    2. jboot.datasource.url=jdbc:mysql://127.0.0.1:3306/jbootsharding
    3. jboot.datasource.user=root
    4. jboot.datasource.password=
    5. jboot.datasource.shardingEnable=true

    进行UserModel保存到数据库

    1. @RequestMapping("/sharding")
    2. public class ShardingController extends JbootController {
    3. public void index() {
    4. UserModel user = new UserModel();
    5. user.setId(StringUtils.uuid());
    6. user.setName("Michael yang");
    7. user.save();
    8. renderText("插入数据成功,请查看数据库...");
    9. }
    10. public static void main(String[] args) {
    11. Jboot.run(args);
    12. }
    13. }

    https://gitee.com/fuhai/jboot/tree/master/src/test/java/sharding