jfinal(7)—数据库操作

1、数据库配置

1.1 ActiveRecord

Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object关系数据库的映射。应用Active Record 时,每一个类的实例对象唯一对应一个数据库表的一行(一对一关系)。你只需继承一个abstract Active Record 类就可以使用该设计模式访问数据库,其最大的好处是使用非常简单。

1.2 ActiveRecordPlugin

ActiveRecord 是作为 JFinal 的 Plugin 而存在的,所以使用时需要在 JFinalConfig(我们 的 是 LearningConfig) 类 的 configPlugin 插 件 配 置 方 法 中 进 行 配 置 ActiveRecordPlugin,这也是目前我们接触到的第一个插件配置,以下是Plugin配置示例代码:

public class LearnConfig extends JFinalConfig {
    
    

 public void configPlugin(Plugins me) {
    
    
 //配置数据连接池,连接数据库(配置一般放在配置文件里)
 DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost:3307/JFinalLearning","root", "root");
 me.add(dp);
 //配置数据库对应的ActiveRecordPlugin(每个数据库一个独立的)
 ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
 me.add(arp);
    /**
     * 配置表的映射关系,当数据表的主键名为“id” 时,可以不用指明主键,使用第一种方法配置即可,
     * 但是如果主键是其他名称时,则需要手动指定,如:arp.addMapping("role", "roleId", Role.class)
     */
 //arp.addMapping("account", Account.class);
 //arp.addMapping("role", "roleId", Role.class);
 }
}

以上代码配置了两个插件:DruidPlugin与ActiveRecordPlugin,前者是druid数据源插件,后者是ActiveRecrod支持插件。ActiveReceord中定义了addMapping(StringtableName, Class<? extends Model> modelClass>)方法,该方法建立了数据库表名到Model的映射关系,

不要忘了引入数据库驱动和数据源哦!这里用的是 Mysql 和 Druid

        <!--数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.29</version>
        </dependency>

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

JFinal 内置的数据源插件有3个,分别是c3p0、druid、HikariCp;

2、操作数据库之 Model模式

2.1 定义Model

Model 是 ActiveRecord 中最重要的组件之一,它充当MVC模式中的 Model 部分。以下是 Model 定义示例代码:

public class Account extends Model<Account> {
    
    
 public static final Account dao = new Account().dao();
}

以上代码中的 Account 通过继承Model,便立即拥有的众多方便的操作数据库的方法。基于ActiveRecord的Model无需定义属性无需定义getter、setter方法无需XML配置无需Annotation配置,极大降低了代码量。

2.2 配置

在这里插入图片描述

2.3 常用方法

// 创建Account对象并添加到数据库
new Account().set("nickName", "nickName1").set("userName", "userName1").save();

// 删除id值为37的Account
Account.dao.deleteById(37);

// 查询id值为38的Account将其password属性改为123并更新到数据库
Account.dao.findById(38).set("password", "123").update();

// 查询id值为38的Account, 且仅仅取nickName与userName两个字段的值
Account.dao.findByIdLoadColumns(38, "nickName, userName");

// 查询所有status=1的Account (手写 SQL 进行 find) 
List<Account> accounts = Account.dao.find("select * from account t where t.status = '1'");
// 分页查询
Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user where status = ?", 1);

//Model 对象的属性其实就是数据库表的列名

// 获取Account的nickName属性
String nickName = account.getStr("nickName");
// 获取Account的id属性
int id = account.getInt("id");

3、操作数据库之 Model与Bean合体模式

普通的 Model 获取属性是需要手动输入属性名的,其实就是数据库表的字段名,当数据表或者字段比较多的时候有很大的记忆工作,使用并不友好。另外,这种没有属性的 Model 在使用针对于Bean设计的第三方工具时也有一定的问题。所以 JFinal 给出了 Model 与传统 JavaBean 合体的解决方法。合体后的 Model 与java bean,立即拥有了 getter、setter 方法,使之遵守传统的 java bean 规范,立即拥有了传统 JavaBean 所有的优势,开发过程中不再需要记忆字段名。

3.1 生成器Generator

ActiveRecord 模块的 com.jfinal.plugin.activerecord.generator 包下,提供了一个Generator 工具类,可自动生成 Model、BaseModel、MappingKit、DataDictionary 四类文件。
使用生成器通常只需配置Generator的四个参数即可,以下是具体使用示例:

  1. baseModelPackageName:base model 的包名;
  2. baseModelOutputDir:baseModel的输出路径;
  3. modelPackageName:model 的包名;
  4. modelOutputDir:model 的输出路径;
public class MyGenerator {
    
    
	public static void main(String[] args) {
    
    
		//部分功能使用 Db + Record 模式实现,无需生成 model 的 table 在此配置,就是需要过过滤的表
//		private static String[] excludedTable = {
    
    
//			"accountRole",
//			"rolePermission"
//		};
				
		DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost:3307/JFinalLearning", "root", "root");//配置数据库
		dp.start();//手动启动插件 

		String baseModelPackageName = "dataBase.model.base";// base model 所使用的包名
		//base model 文件保存路径
		String baseModelOutputDir = PathKit.getWebRootPath()+ "/src/main/java/dataBase/model/base";

		
		String modelPackageName = "dataBase.model";// model 所使用的包名 (MappingKit 默认使用的包名)
		String modelOutputDir = baseModelOutputDir + "/..";// model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)

		// 创建生成器
		Generator gen = new Generator(dp.getDataSource(), baseModelPackageName,
				baseModelOutputDir, modelPackageName, modelOutputDir);

		// 设置是否生成字段备注
		gen.setGenerateRemarks(true);
		// 设置是否在 Model 中生成 dao 对象
		gen.setGenerateDaoInModel(false);
		// 生成
		gen.generate();
	}

}

3.2 生成的文件

  1. BaseModel是用于被最终的Model继承的基类,所有的getter、setter方法都将生成在此文件内,这样就保障了最终Model的清爽与干净,BaseModel不需要人工维护,在数据库有任何变化时重新生成一次即可
  2. MappingKit用于生成table到Model的映射关系,并且会生成主键/复合主键的配置,也即无需在configPlugin(Plugins
    me)方法中书写任何样板式的映射代码
  3. DataDictionary是指生成的数据字典,会生成数据表所有字段的名称、类型、长度、备注、是否主键等信息。

3.3 使用方法

合同后的 Model 使用有一个很大的简化就是不需要再记录数据库的表名,可以直接通过 setter、getter 方法来操作属性,
除此之外原始 Model 具备的功能仍然具备:

db.model.Account User= new db.model.User();
account.setNickName("nickName2");
account.setUserAge(22);
account.save();

4、操作数据库之 DB+Record模式

4.1 常见用法

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

// 创建account的record对象并添加到数据库
Record account = new Record().set("nickName","nickName3").set("userName", "userName3");
Db.save("account", account);//第一个参数是数据库表名

// 删除id值为25的account表中的记录
Db.deleteById("account", 25);

// 查询id值为25的Record将其name属性改为James并更新到数据库
account = Db.findById("account", 25).set("nickName","nickName4");
Db.update("account", account);

// 获取Account的nickName属性
String nickName = account.getStr("nickName");
// 获取Account的id属性
int id = account.getInt("id");
// 查询所有年龄大于18岁的user
List<Record> users = Db.find("select * from account t where t.status = '1'");

// 分页查询年龄大于18的user,当前页号为1,每页10个user
Page<Record> userPage = Db.paginate(1, 10, "select *", "from account t where t.status = ?", 1);

简单归纳下 DB+Record 的用法(对比着Model的用法):

1、同样拥有save、delete、update、find等一系列直接操作数据库的方法,不过由于没有映射表,所以操作的时候需要明确操作的表名
2、同样支持手写 SQL 进行save、delete、update、find等一系列操作,方法更加灵活;
3、Record 对象的属性其实就是数据库表的列名,使用时需要注意属性名和数据库表列名的关系
4、对分页提供了很友好的支持
5、比 Model 多出一个query系列方法

4.2 DB的query系列方法

4.2.1 Db.query

第一种用法:当 select 后的字段只有一个时,可以使用合适的泛型接收数据:

List<String> nickNames = Db.query("select nickName fromaccount");
List<Integer> idList = Db.query("select id from account");

第二种用法:当 select 后的字段有多个时,必须使用 List<Object[]> 接收数据,例如

List<Object[]> list = Db.query("select nickName,userName from account");
List<Object[]> list = Db.query("select * from account");
4.2.2 queryXxx

Db.queryXxx 系方法有:queryInt、queryLong、queryStr 等等,这些方法对于使用聚合函数这类的 sql 十分方便,例如:
以下 sql 使用了 count(*) 聚合函数,使用 Db.queryInt 不仅方便而且性能是最好的

int total = Db.queryInt("select count(*) from account");

除了聚合函数以外,还可以用于查询某条记录的某个字段值,例如:
以下代码通过 queryStr 可以很方便去查询 id 值为 123 的 account 的 nickName。

String nickName = Db.queryStr("select nickName from account where id = ?", 123);

可以看出来,Db.queryXxx 系方法要求 select 后面必须只能有一个字段名,或者说只能返回一个 column 值(例如 count(*)),查询结果只能是一个值。

4.2.3 Db.find 系与 Db.query/Db.queryXxx系的区别

前者将返回值一律封装到一个 Record 对象中,而后者不封装,只将数据原样返回。查询所使用的 sql 与参数用法完全一样。

猜你喜欢

转载自blog.csdn.net/qq_45928727/article/details/108899899