sorms簡(jiǎn)易 ORM 框架
簡(jiǎn)易ORM框架
此框架主要為在使用Spring框架的以下用戶考慮:
喜歡JPA注解,但討厭hibernate和spring data jpa效率低下的.同時(shí)又不想失去sql靈活性的.
喜歡Mybatis的直接,但對(duì)mybatis的易用性和可維護(hù)性提出質(zhì)疑的.
此框架在hibernate和mybatis做了折中,并且執(zhí)行性能超過(guò)兩者.
此框架主要基于ef-orm框架理念
使用jpa注解,但不完全實(shí)現(xiàn)jpa規(guī)范,單表增,刪,改比較方便,同時(shí)對(duì)級(jí)聯(lián)也做了支持,但不實(shí)現(xiàn)延遲加載功能,必須手動(dòng)調(diào)用,才能加載級(jí)聯(lián)對(duì)象(此處主要降低jpa實(shí)現(xiàn)復(fù)雜度).
jpa支持注解如下: @Column,@Table,@Entity,@Id,@OneToOne,@OneToMany,@ManyToMany,@ManyToOne.@JoinColumn,@JoinTable,@Version
使用了代碼增強(qiáng)技術(shù),增強(qiáng)了實(shí)體類.需要繼承DBObject類.并使用配置實(shí)現(xiàn)代碼增強(qiáng).繼承DBObject類的java bean 只要調(diào)用set方法即可精確修改數(shù)據(jù)庫(kù)對(duì)象.
支持級(jí)聯(lián)配置
支持Map格式的數(shù)據(jù)對(duì)象返回.
支持使用模板寫(xiě)sql,主要使用jetbrick-template實(shí)現(xiàn).
支持對(duì)象操作的樂(lè)觀鎖功能.
支持實(shí)體對(duì)象生成功能
不支持一級(jí),二級(jí)緩存(Spring cache已經(jīng)足夠好)
整合支持querydsl,jooq用法,提高系統(tǒng)可維護(hù)性.能降低80%~90%的sql硬編碼.極大提高系統(tǒng)的可維護(hù)性.
支持mybatis的resultMap,但無(wú)需編寫(xiě)xml,只需使用@Column注解和數(shù)據(jù)庫(kù)字段映射即可,對(duì)于一條sql語(yǔ)句對(duì)應(yīng)一個(gè)主類帶子類對(duì)象,使用@OneToOne注解標(biāo)記即可實(shí)現(xiàn)主類、子類的組裝.
此框架為整合性框架,感謝ef-orm,jfinal,BeetlSQL,Nutz,mybatis,jetbrick-orm
快速預(yù)覽
spring 環(huán)境下
@Bean
public OrmConfig getOrmConfig(DaoTemplate dt) {
OrmConfig config = new OrmConfig();
config.setPackagesToScan(StringUtils.split("db.domain",","));
config.setDbClient(dt);
config.setUseTail(true);
config.setFastBeanMethod(false);
config.init();
return config;
}
@Bean(name="daoTemplate")
public DaoTemplate geDaoTemplate(DataSource ds) {
DaoTemplate dt = new DaoTemplate(ds);
return dt;
}
spring boot直接配置 application.properties中配置
#jpa實(shí)體類所在的包 smallorm.packages=db.domain ...
spring boot中的main方法啟動(dòng)中加入增強(qiáng)的代碼
public static void main(String[] args) throws Exception {
//jpa實(shí)體類所在的包
new EntityEnhancerJavassist().enhance("db.domain");
SpringApplication.run(SefApplication.class, args);
}
引入spring-boot-jdbc-starter
3.編寫(xiě)jpa實(shí)體類
package db.domain;
import sf.database.DBCascadeField;
import sf.database.DBField;
import sf.database.annotations.Comment;
import sf.database.annotations.FetchDBField;
import sf.database.annotations.Type;
import sf.database.jdbc.extension.ObjectJsonMapping;
import sf.database.DBObject;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.*;
@Entity
@Table(name = "wp_users")
@Comment("用戶表")
public class User extends DBObject {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "login_name", length = 60, nullable = false)
private String loginName;// 登陸名
@Column(length = 64)
private String password;
@Column(length = 50)
private String nicename;
@Column(length = 100)
private String email;
@Column(length = 100)
private String url;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date registered;
/**
* 激活碼
*/
@Column(name = "activation_key", length = 60, nullable = false)
private String activationKey;
@Column
private int status;
@Column(name = "display_name", length = 250)
@Enumerated(EnumType.STRING)
private Names displayName;
@Column
private Boolean spam;
@Column
private boolean deleted;
@Column(precision = 10,scale = 5)
private BigDecimal weight;
@Transient
private boolean lock;
@Column(name = "maps",length = 1500)
@Type(ObjectJsonMapping.class)
private Map<String,String> maps;
@ManyToMany
@Transient
@OrderBy("id asc,role desc")
@JoinTable(name = "user_role", joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {
@JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<Role> roles;
@OrderBy
@Transient
@FetchDBField({"id","key"})
@OneToMany(targetEntity = UserMeta.class)
@JoinColumn(name = "id", referencedColumnName = "userId")
private Set<UserMeta> userMetaSet = new LinkedHashSet<UserMeta>();
public enum Names {
zhangshang, lisi
}
/**
* 普通字段
*/
public enum Field implements DBField {
id, loginName, password, nicename, email, url, registered, activationKey, status, displayName,maps, spam, deleted,weight;
}
/**
* 級(jí)聯(lián)字段
*/
public enum CascadeField implements DBCascadeField {
roles, userMetaSet
}
public User() {
}
... get set方法
}
在dao中引入
@Resource private DaoTemplate dt;
以daoTemplate操作sql方法.
插入對(duì)象
User user = dt.selectOne(new User());
User u = new User();
u.setLoginName(UUID.randomUUID().toString());
u.setDeleted(false);
u.setCreated(new Date());
u.setActivationKey("23k4j2k3j4i234j23j4");
//插入對(duì)象,生成的語(yǔ)句為:insert into wp_users(activation_key,created,deleted,login_name) values(?,?,?,?)
int i = dt.insert(u);
執(zhí)行原生sql
String sql = "select * from wp_users"; List<User> list = dt.selectList(User.class, sql);
執(zhí)行模板sql
#tag loadSql("queryUserByName")
#[[
select * from wp_users
#tag where()
#if(id)
and id=${p(id)}
#end
#if(username)
and login_name=${p(username)}
#end
#if(nicename)
and nicename=${p(nicename)}
#end
#end
]]#
#end
java代碼
Map<String, Object> query = new HashMap<>();
query.put("id", 1);
List<User> list2 = dt.selectListTemplate(User.class, "queryUserByName", query);
執(zhí)行Querydsl
SQLRelationalPath<User> q = QueryDSLTables.relationalPathBase(User.class); SQLQuery<User> query = new SQLQuery<User>(); query.select(q).from(q).where(q.string(User.Field.displayName).isNotNull()) .orderBy(new OrderSpecifier<>(Order.ASC, q.column(User.Field.id))); Page<User> page = dt.sqlQueryPage(query, 2, 3);
執(zhí)行jooq代碼
JooqTable<?> quser = JooqTables.getTable(User.class); JooqTable<?> qrole = JooqTables.getTable(Role.class); Select<?> query = DSL.select(quser.fields()).from(quser, qrole).where(quser.column(User.Field.id).eq(1)); User u = dt.jooqSelectOne(query);
