lit-jdbc 是一个简单易用的jdbc工具,
可以在service或其他需要的地方注入 JdbcTools 来完成对数据库的操作
目前 还没有发布到maven**库, 可以 install 到本地库, 通过 maven 引用
<dependency>
<groupId>net.skeyurt.lit</groupId>
<artifactId>lit-jdbc</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
然后在配置类中添加 @EnableLitJdbc
注解即可, 前提是已经配置了数据源 或 JdbcOperations 的bean
@Configuration
@EnableLitJdbc
public class SpringConfig {
// 其他配置
}
如果是使用 xml
配置的话, 配置 JdbcToolsConfig
bean
<bean class="net.skeyurt.lit.jdbc.spring.config.JdbcToolsConfig">
</bean>
配置完成后, 就可以在 service 中注入 JdbcTools
对实体进行操作, 基本不在需要 dao 了
实体与数据库表的对应关系:
类名 对应表名, 默认驼峰转下划线
主键 默认类名 + Id 首字母小写的驼峰命名
属性名 对应表字段名, 默认驼峰转下划线
如果不想使用默认转换规则, 可以使用 @Table
, @Column
, @Id
, @Transient
注解
下面以商品实体为例, 介绍 JdbcTools 的具体用法, 数据库是 MySql
@Table(name = "lit_goods")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Goods implements Serializable {
private static final long serialVersionUID = -7915472099544797458L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long goodsId; // 商品编码
private String code; // 编码
private String barCode; // 条形码
private String specification; // 规格
private String unit; // 单位
private String category; // 分类
private String purchaserCode; // 采购员
private String supplierCode; // 供应商
private String name; // 品名
private Double price; // 售价
private Integer inventory; // 库存
private Date gmtCreate; // 创建时间
}
public void testInsert() {
Goods goods = new Goods();
goods.setCode("80145124");
// ...
Long id = (Long) jdbcTools.insert(goods);
log.info("插入的实体ID为: {}", id);
}
insert 操作会返回实际插入数据库后的主键值, 自增长和 SEQUENCE 会返回 Long 型.
-
数据库自增长
@GeneratedValue(strategy = GenerationType.IDENTITY) private Long goodsId; // 商品编码
-
使用数据库序列, 如果没有指定
sequenceName
, 默认是seq_
+ 表名@GeneratedValue(strategy = GenerationType.SEQUENCE, sequenceName = "seq_goods") private Long goodsId; // 商品编码
-
自定义主键生成, 实现
KeyGenerator
接口的类都可以作为主键生成类@GeneratedValue(generator = UUIDGenerator.class) private Long goodsId; // 商品编码
还支持下面这种操作方式:
@Test
public void testInsert() {
Long id = (Long) jdbcTools.createInsert(Goods.class)
.into("code", "80145412")
.into("name", "农夫山泉")
.into("price", 2D)
.execute();
log.info("插入的实体ID为: {}", id);
}
@Test
public void testUpdate() {
// update 操作是根据实体的 id 来更新记录, 所以要保证实体中的 Id一定不为空
Goods goods = new Goods();
goods.setGoodsId(12301L);
goods.setName("康师傅绿茶");
//方式一 实体中值为 null 的属性 不会 更新到数据库中
jdbcTools.update(goods);
//方式二 实体中值为 null 的属性 会 更新到数据库中,
jdbcTools.update(goods, false);
}
或者
@Test
public void testUpdate2() {
// 会将 code 为 80145412 的商品的 name 和 price 更新, 返回受影响记录的条数
int rows = jdbcTools.createUpdate(Goods.class)
.set("name", "统一红茶")
.set("price", 3.0D)
.where("code", "80145412")
.execute();
}
@Test
public void testDelete() {
Goods goods = new Goods();
goods.setGoodsId(1200L);
// 方式一, 根据实体中的 Id 值删除记录, 返回受影响记录的条数
int rows = jdbcTools.delete(goods);
// 方式二, 根据一批 id 值 删除指定的实体记录, 返回受影响记录的条数
rows = jdbcTools.deleteByIds(Goods.class, 1200L, 1201L);
// 方式三 删除 code 为 80145412 的商品, 返回受影响记录的条数
rows = jdbcTools.createDelete(Goods.class)
.where("code", "80145412")
.execute();
}
@Test
public void testSelect1() {
Goods goods = jdbcTools.get(Goods.class, 1203L);
}
@Test
public void testSelect2() {
Select<Goods> select = jdbcTools.createSelect(Goods.class)
.where("code", "8014512") // 添加条件 code='8014512'
.and("price", Logic.GTEQ, 20.98D) // 添加条件 and price >= 20.98
.or("inventory", Logic.LT, 120); // 添加条件 or inventory < 120
// 返回 count
int count = select.count();
// 返回 单个 实体对象, 如果查询结果有多条, 会抛出异常, 查询结果为空, 返回 null
Goods goods = select.single();
// 返回实体列表
List<Goods> list = select.list();
// 返回分页查询结果列表, 可以强转 为 PageList, 获取分页信息
List<Goods> pageList1 = select.page(1, 20).list();
// 返回分页查询结果列表, 但是 不会查询 count, 只查询分页结果
List<Goods> pageList2 = select.page(1, 20, false).list();
}
分页查询没有单独的方法, 而是集中在了 list()方法中,
若需要分页查询, 只需要把通过 jdbcTools 获取的 Select
对象设置分页参数( page() 方法), 再通过 list() 获取分页后的结果集,
page()
有 3 个重载方法, 第一个参数是 当前页码 , 第二个参数是 每页条数 , 第三个参数是 是否查询 count
list() 返回的 List 对象, 如果是分页查询, 可以将此 List 强转成 PageList
(一个继承 ArrayList 的 List, 包含分页的相关信息)
@Test
public void testSelect3() {
// 指定白名单, 将只查询 白名单里的字段
List<Goods> goodsList1 = jdbcTools.createSelect(Goods.class)
.include("code", "name") // 只查询 code 和 name
.where("name", Logic.LIKE, "%娃哈哈%") // 条件 name like ? 参数 %娃哈哈%
.andWithBracket("price", Logic.LTEQ, 38.7D) // 添加带有括号的 and条件 and ( price <= ? 参数 38.7
.or("supplierCode", "00776") // 条件 supplier_code=? 参数 00776
.end() // 结束刚才 and 条件添加的括号 )
.list(); // 查询列表
// 指定黑名单, 除了黑名单里的字段, 其他全部查询
List<Goods> goodsList2 = jdbcTools.createSelect(Goods.class)
.exclude("code", "name") // 查询将排除 code 和 name
.list(); // 查询列表
}
注: 如果添加了函数, 就只会把 include (白名单) 的字段 和添加的函数 放到 select 后
@Test
public void testSelect4() {
// 1. 指定函数名, 默认全部字段, 结果会添加 count(*)
Integer count = jdbcTools.createSelect(Goods.class)
.addFunc("count")
.single(Integer.class); // 指定函数返回类型
// 2. 指定函数名和字段, 结果会添加 max(price)
jdbcTools.createSelect(Goods.class)
.addFunc("max", "price")
.single(Double.class); // 指定返回类型
// 3. 指定函数名和字段, 第二个参数是 isDistinct, 结果会添加 count( distinct supplier_code )
jdbcTools.createSelect(Goods.class)
.addFunc("count", true, "supplierCode")
.single(Integer.class);
}
上面只添加了一个函数, 返回的是简单类型, 如果 select 后面有多个函数, 且想把返回记录绑定到对象的属性上, 可以将函数的别名设置为对象的属性名
@Test
public void testSelect5() {
// 为函数指定别名 和 查询结果的 返回类型
// max(price) 的查询结果将会绑定到 GoodsVo 的 maxPrice 属性上
// count(inventory) 的查询结果将会绑定到 GoodsVo 的 inventoryCount 属性上
jdbcTools.createSelect(Goods.class)
.addFunc("max", "price")
.addFunc("count", "inventory")
.alias("maxPrice", "inventoryCount")
.single(GoodsVo.class); // 指定返回类型
// 另一种写法
jdbcTools.createSelect(Goods.class)
.addFunc("max", "price").alias("maxPrice")
.addFunc("count", "inventory").alias("inventoryCount")
.single(GoodsVo.class);
}
@Test
public void testSelect6() {
// 注: asc 和 desc 方法 可以放多个字段
List<Goods> list = jdbcTools.createSelect(Goods.class)
.where("name", Logic.LIKE, "%娃哈哈%")
.asc("code") // 按 code 升序排列
.desc("gmtCreate") // 按创建时间降序排列
.list();
}
@Test
public void testSelect7() {
// 按供应商代码 supplierCode 查询 最大价格和最大库存
jdbcTools.createSelect(Goods.class)
.include("supplierCode")
.addFunc("max", "price")
.addFunc("max", "inventory")
.alias("maxPrice", "maxInventory")
.where("price", Logic.GTEQ, 19.98)
.and("inventory", Logic.GTEQ, 10)
.groupBy("supplierCode")
// 添加 having 条件
.having("maxPrice", Logic.GTEQ, 198)
.and("maxInventory", Logic.GTEQ, 100)
.list(GoodsVo.class);
}
以供应商表为关联表示例
@Table(name = "lit_supplier")
@Data
@Builder
public class Supplier implements Serializable {
private static final long serialVersionUID = 548793140920612818L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long supplierId;
private String code;
private String name;
private String address;
private String contact;
private String telephone;
private String mobile;
}
写法如下:
@Test
public void testSelect8() {
jdbcTools.createSelect(Goods.class)
// join 语句, 和 on 一起使用 设置关联条件
.join(Supplier.class)
.on(Supplier.class, "code", Logic.EQ, Goods.class, "supplierCode")
// 添加 供应商表中的字段
.addField(Supplier.class, "name")
.addField(Supplier.class, "address")
// 设置别名, 与 GoodsVo 中属性名一致,
.alias("supplierName", "supplierAddr")
.where("price", Logic.GTEQ, 19.98)
.list(GoodsVo.class);
}
这样 join 条件 会用 on 连接
SELECT lit_supplier.name AS supplierName, lit_supplier.address AS supplierAddr, lit_goods.unit, lit_goods.goods_id, lit_goods.category, lit_goods.price, lit_goods.gmt_create, lit_goods.purchaser_code, lit_goods.inventory, lit_goods.name, lit_goods.specification, lit_goods.bar_code, lit_goods.supplier_code, lit_goods.code
FROM lit_goods JOIN lit_supplier ON lit_supplier.code = lit_goods.supplier_code WHERE price >= ?
还可以使用简单 join 将关联条件放到 where 中
@Test
public void testSelect9() {
jdbcTools.createSelect(Goods.class)
// 使用简单join 需要和 joinCondition 一起使用设置关联条件
.simpleJoin(Supplier.class)
// 添加 供应商表中的字段
.addField(Supplier.class, "name")
.addField(Supplier.class, "address")
// 设置别名, 与 GoodsVo 中属性名一致,
.alias("supplierName", "supplierAddr")
.joinCondition(Supplier.class, "code", Logic.EQ, Goods.class, "supplierCode")
.and("price", Logic.GTEQ, 19.98)
.list(GoodsVo.class);
}
结果如下:
SELECT lit_supplier.name AS supplierName, lit_supplier.address AS supplierAddr, lit_goods.unit, lit_goods.goods_id, lit_goods.category, lit_goods.price, lit_goods.gmt_create, lit_goods.purchaser_code, lit_goods.inventory, lit_goods.name, lit_goods.specification, lit_goods.bar_code, lit_goods.supplier_code, lit_goods.code
FROM lit_goods, lit_supplier WHERE lit_supplier.code = lit_goods.supplier_code AND price >= ?
以上内容 若有不正确的地方, 欢迎指出