背景

由于工作的一些原因,需要从C#转成JAVA。之前PetaPoco用得真是非常舒服,在学习JAVA的过程中熟悉了一下JAVA的数据组件:

  • MyBatis 非常流行,代码生成也很成熟,性能也很好。但是DEBUG的时候不方便,且XML写SQL也不是很适应,尤其是团队比较小没有专职DBA的情况下。
  • Hibernate 使用过NHibernate,做企业应用倒是挺适合的。掌握并用好它不是一件很容易的事情,尤其是团队水平不够,目标项目为互联网游戏平台的时候。
  • sql2o 开源项目,轻量级的ORM,与Dapper,PetaPoco非常类似,感觉上还是没有PetaPoco好用。

基于以上的理解,便打算造一个JAVA版的PetaPoco —— PataPojo

  • 处于学习JAVA阶段,能够学习并使用一些高级语法
  • 理解JAVA的基础数据库组件
  • 若开发成功,则原有的团队与项目基本上能够很好地迁移至JAVA开发环境,提升开发效率

功能概述

  • 轻量级
  • 用于简单的POJO
  • 泛型的增删改查的帮助方法提供
  • 自动分页,自动计算出总记录数及页数据
  • 简单的事务支持
  • 暂时仅支持MYSQL
  • 更好的参数支持
  • 仍然使用SQL语法,并提供强大的Sql生成器类
  • 开源

下载

怎么使用

引用jar包

下载petapojo.jar包后,在项目中进行引用

执行查询

实体Mapping

// 对应表 user_info
@TableName("user_info")
// 主键映射,字段名,是否自增
@PrimaryKey(value = "id",autoIncrement = true)
public class UserInfo { private int id;
private String userName; // 列名与字段名的映射 (若无注解,则按字段名映射为列名)
@Column("password")
private String password; // 该字段不进行映射
@Ignore
private String none; //... getter and setter
}

下一步,使用database.java进行查询:


DruidDataSource dataSource = new DruidDataSource();
// 配置dataSource
// ...
Database database = new Database(dataSource);
List<UserInfo> userList = database.query(UserInfo.class, "SELECT * FROM user_info"); for (UserInfo userInfo : userList) {
System.out.println(userInfo.getUserName());
}

查询第一行第一列:

Integer number = database.executeScalar(Integer.class,
"SELECT COUNT(1) FROM user_info");

或者,查找第一条记录:

UserInfo userInfo = database.firstOrDefault(UserInfo.class,
"SELECT * FROM user_info WHERE id = ?",123);

分页

// 参数说明:
// 1 - 页索引
// 10 - 页大小
// 20 - 是指 age > ? 的参数值
PageInfo<UserInfo> pagedList = database.pagedList(UserInfo.class, 1,10,
"SELECT * FROM user_info WHERE age > ? ORDER BY createDate DESC",20);

返回的PageInfo描述:

/**
* 分页泛型
*/
public class PageInfo<T> {
// 当前页索引
private int currentPage;
// 总页数
private int totalPages;
// 总记录数
private int totalItems;
// 每页记录数
private int itemsPrePage;
// 当前页列表
private List<T> items; public PageInfo() {
items = new ArrayList<>();
} // ...
// getter and setter
}

执行没有返回的SQL:

// 返回影响行数
int row = database.executeUpdate("DELETE FROM user_info WHERE id = ?",123);

实体的增删改
新增:

UserInfo userInfo = new UserInfo();
userInfo.setUserName("PetaPojo");
userInfo.setPassword("123123"); database.insert(userInfo);

修改:

UserInfo userInfo = database.firstOrDefault(UserInfo.class,
"SELECT * FROM user_info WHERE id = ?", 1);
userInfo.setPassword("123456"); database.update(userInfo);

删除:

UserInfo userInfo = database.firstOrDefault(UserInfo.class,
"SELECT * FROM user_info WHERE id = ?", 1);
database.delete(userInfo); // 或者 根据主键删除
database.delete(UserInfo.class,1); // 或者 根据条件进行删除
database.delete(UserInfo.class,"WHERE id = ?",1);

自动添加查询列

当我们在使用ORM时,我们常常需要先编写查询列名及表名的SQL语句SELECT * FROM user_info,其实是非常影响开发效率的。
因此,PetaPojo增加了自动添加查询列与表名的自动匹配功能。
例如:

UserInfo userInfo = database.firstOrDefault(UserInfo.class,
"SELECT * FROM user_info WHERE id = ?", 1);

PetaPojo可以允许简化为:

UserInfo userInfo = database.firstOrDefault(UserInfo.class,"WHERE id = ?",1);

查询组装器 Sql Builder

在我们查询数据库时,经常需要添加一些条件或排序之类的。总之,尽可能地让SQL语句动态化或更灵活,以应对复杂的业务需要。
与此同时,如果我们只是进行单纯的SQL硬编写,开发效率将会是一个很大的问题,维护亦比较复杂费时。

在此基础上,PetaPojo提供了一个非常便捷的SQL查询组装器。

基础模式:

int id = 1;
Sql sql = Sql.create()
.append("SELECT * FROM user_info")
.append("WHERE id = ?",id);
UserInfo userInfo = database.firstOrDefault(UserInfo.class,sql);

或者:

int id = 1;
Sql sql = Sql.create()
.append("SELECT * FROM user_info")
.append("WHERE id = ?", id)
.append("AND createDate >= ?", DateTime.now());
UserInfo userInfo = database.firstOrDefault(UserInfo.class, sql);

同样,可以根据不同的条件来进行组装:

int id = 1;
Sql sql = Sql.create()
.append("SELECT * FROM user_info")
.append("WHERE id <> ?", id) if(age != null)
sql.append("AND age > ?", age); if(startDate != null)
sql.append("AND createDate >= ?", startDate); List<UserInfo> userList = database.query(UserInfo.class,sql);

在SQL组装时,参数列表是无限的,只需要与SQL语句中的参数替代符?相匹配即可,如:

int id = 1;
DateTime now = DateTime.now(); Sql sql = Sql.create()
.append("SELECT * FROM user_info")
.append("WHERE id <> ? AND createDate >= ?", id, now); List<UserInfo> userList = database.query(UserInfo.class,sql);

Sql.append的基础上,PetaPojo提供了更为便捷的链式函数:

Sql sql = Sql.create()
.select("*")
.from("user_info")
.where("id = ?", 1)
.where("createDate >= ?", DateTime.now().toString())
.where("age >= ? AND age <= ?", 10, 20)
.orderBy("createDate DESC"); PageInfo<UserInfo> pagedList = database.pagedList(UserInfo.class,1,10,sql);

基于自动添加查询列的功能,上述语句可变改为:

Sql sql = Sql.create()
.where("id = ?", 1)
.where("createDate >= ?", DateTime.now())
.where("age >= ? AND age <= ?", 10, 20)
.orderBy("createDate DESC"); PageInfo<UserInfo> pagedList = database.pagedList(UserInfo.class,1,10,sql);

因此,在一些复杂的查询中,我们可这样用:

int id = 1;
Sql sql = Sql.create()
.where("id <> ?", id) if(age != null)
sql.where("age > ?", age); if(startDate != null)
sql.where("createDate >= ?", startDate); sql.orderBy("createDate DESC"); List<UserInfo> userList = database.query(UserInfo.class,sql);

枚举支持

在开发中,经常会碰到一些需要使用枚举的地方,如订单状态,用户类型等。
JAVA默认枚举类型不是很好用,最主要的问题在于:用户类型,订单状态这些枚举在系统中我们可以理解为一个键值对的列表,而JAVA默认枚举的index是不可自定义的。

因此,PetaPojo在枚举的支持上做了一些扩展。

首先,PetaPojo定义了一个枚举接口:

/**
* 枚举必须要实现的接口
*/
public interface IEnumMessage { int getValue(); String getName();
}

并提供了一个枚举帮助类:

public class EnumUtils {

    private static final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
private static final ReentrantReadWriteLock.ReadLock rl = rrwl.readLock();
private static final ReentrantReadWriteLock.WriteLock wl = rrwl.writeLock();
private static Map<Class<? extends IEnumMessage>, Map<Integer, IEnumMessage>> ENUM_MAPS = new HashMap<>(); /**
* 根据key以及枚举类型,得到具体的枚举对象
*/
public static <T extends IEnumMessage> T getEnum(Class<T> type, int value) {
return (T) getEnumValues(type).get(value);
} /**
* 将枚举类型转化为一个键值对的Map
*/
public static <T extends IEnumMessage> Map<Integer, String> getEnumItems(Class<T> type) {
Map<Integer, IEnumMessage> map = getEnumValues(type);
Map<Integer, String> resultMap = new HashMap<>();
map.forEach((k, v) -> {
resultMap.put(k, v.getName());
});
return resultMap;
} private static <T extends IEnumMessage> Map<Integer, IEnumMessage> getEnumValues(Class<T> clazz) {
rl.lock();
try {
if (ENUM_MAPS.containsKey(clazz))
return ENUM_MAPS.get(clazz);
} finally {
rl.unlock();
} wl.lock();
try {
if (ENUM_MAPS.containsKey(clazz))
return ENUM_MAPS.get(clazz); Map<Integer, IEnumMessage> map = new HashMap<>();
try {
for (IEnumMessage enumMessage : clazz.getEnumConstants()) {
map.put(enumMessage.getValue(), enumMessage);
}
} catch (Exception e) {
throw new RuntimeException("getEnumValues error", e);
}
ENUM_MAPS.put(clazz, map); return map;
} finally {
wl.unlock();
}
}
}

进而,在项目使用枚举(如UserType)时,实现IEnumMessage接口即可:


/**
* 用户类型
*/
public enum UserType implements IEnumMessage { Student(1,"学生"),
Teacher(2,"老师"),
Coder(4,"码农"); private int value;
private String name; UserType(int value,String name){
this.value = value;
this.name = name;
} @Override
public int getValue() {
return this.value;
} @Override
public String getName() {
return this.name;
}
}

对应的实体:

@TableName("user_info")
@PrimaryKey(value = "id",autoIncrement = true)
public class UserInfo { private int id;
private String userName;
private String password; // 直接使用枚举,数据库中作为int型进行存储
private UserType userType; // ... getter setter
}
UserInfo userInfo = database.firstOrDefault(UserInfo.class,
"SELECT * FROM user_info WHERE id = ?",1);
// 设置用户类型为码农
userInfo.setUserType(UserType.Coder); database.update(userInfo);

时间类型支持 org.joda.time.DateTime

PetaPojo支持org.joda.time.DateTime类型,映射的数据库表字段类型为datetime

@TableName("user_info")
@PrimaryKey(value = "id",autoIncrement = true)
public class UserInfo { private int id;
private String userName;
private String password; // 直接使用枚举,数据库中作为int型进行存储
private UserType userType; private DateTime createDate; // ... getter setter
}

当SQL查询中的参数值为org.joda.time.DateTime时,这样使用:

Sql sql = Sql.create()
.where("createDate >= ?",DateTime.now().toString());
// 将DateTime类型toString即可

以上便是整体PetaPojo的主要功能。

PetaPojo —— JAVA版的PetaPoco的更多相关文章

  1. ArcGIS Server 10 Java 版的Rest服务手动配置方法

    Java版的Manager中发布的服务默认只发布了该服务的SOAP接口,而REST接口需要用户在信息服务器,如Tomcat. Apache.WebLogic等中手工配置.由于在Java版的Server ...

  2. 【转载】java版打字练习软件

    网上找到一个java版的打字的游戏 import java.applet.Applet; import java.applet.AudioClip; import java.awt.Dimension ...

  3. 微博地址url(id)与mid的相互转换 Java版

    原理: 新浪微博的URL都是如:http://weibo.com/2480531040/z8ElgBLeQ这样三部分. 第一部分(绿色部分)为新浪微博的域名,第二部分(红色部分)为博主Uid,第三部分 ...

  4. JCEF3——谷歌浏览器内核Java版实现(一):使用jawt获取窗体句柄

    前言 最近一段时间研究谷歌浏览器内核.谷歌浏览器内核一直开源,并维护更新,它的开源项目中内核更新速度和Chrome浏览器版本更新进度一样!而且它不同于WebKit(值得一题的是谷歌浏览器已不使用Web ...

  5. Selenium关键字驱动测试框架Demo(Java版)

    Selenium关键字驱动测试框架Demo(Java版)http://www.docin.com/p-803493675.html

  6. 第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容

    第一部分:微信JS-SDK介绍 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统 ...

  7. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

  8. 第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同). 公众号可通过本接口来根据O ...

  9. 第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    我们来了解一下 自定义菜单创建接口: http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

随机推荐

  1. zabbix3.2安装graphtree3.0.4

    下载graphtree3.0.4 wget https://raw.githubusercontent.com/OneOaaS/graphtrees/master/graphtree3-0-1.pat ...

  2. 2016,Raym

    Hello,2016: 这是承上启下的一年! Raym

  3. 快速学习C语言二: 编译自动化, 静态分析, 单元测试,coredump调试,性能剖析

    上次的Hello world算是入门了,现在学习一些相关工具的使用 编译自动化 写好程序,首先要编译,就用gcc就好了,基本用法如下 gcc helloworld.c -o helloworld.o ...

  4. 从一个简单例子来理解js引用类型指针的工作方式

    <script> var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x);// --> undefined conso ...

  5. 作业三:PSP记录耗时情况

    PSP2.1 Personal Software Process Stage Time planning 计划 15min Estimate 估计这个任务多久完成 130min Developing ...

  6. [.net 面向对象编程基础] (23) 结束语

    [.net 面向对象编程基础] (23)  结束语 这个系列的文章终于写完了,用了半个多月的时间,没有令我的粉丝们失望.我的感觉就是一个字累,两个字好累,三个字非常累.小伙伴们看我每篇博客的时间就知道 ...

  7. 使用抓包工具SpyNet对你的网络进行监控

    步骤1:下载并安装SpyNet Sniffer嗅探器之后,第一次运行SpyNet Sniffer后,将会弹出[Settings(设置)]对话框,在其中选择需要监听对象,如图所示. 步骤2:单击[Act ...

  8. [php入门] 1、从安装开发环境环境到(庄B)做个炫酷的登陆应用

    1.前言 本文适合想了解下web开发入门的小白~ 最近在根据一个网上课程学习php,课程内说道: php环境自己搭比较麻烦,可以用wamp集成开发环境,一键安装即可. 2.安装集成开发环境 下面是wa ...

  9. osgi dm

    看了http://developer.51cto.com/art/200909/154863.htm 真心感到,最强大最有组织的技术网站还是 51cto,牛人应该也是最多的. 以前逛51cto的比较少 ...

  10. netstat 1

    lsof -i   :8086 第二个参数需要:开头 netstat linux  -a (all)显示所有选项,默认不显示LISTEN相关 理解这个很关键, 这是为什么我们netstat -a 不显 ...