@eric1989
2016-02-13T10:37:13.000000Z
字数 5883
阅读 667
Jfire-Orm是一个半自动的Orm映射框架,基于方法和Sql语句的映射来进行代码和sql语句的解耦.但是同时也提供快捷的单表对象CURD操作.其中单表curd操作是基于标准sql.
Jfire-Orm并不试图提供大而全的解决方案,而是更希望提供方便于实际编程的解决方式.因为是基于标准sql的,其目标是解决方法最后到sql中的解耦问题.
在Jfire-Orm框架中,使用SqlSession来代表一个数据库连接,而SqlSession是由SessionFactory产生的.所以框架使用的开始就是初始化SessionFactory.
SessionFactory的实现类是SessionFactoryImpl.初始话的时候需要提供一个连接池对象.代码如下.
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("centerm");
dataSource.setMaxActive(150);
dataSource.setMaxWait(500);
try
{
dataSource.getConnection();
}
catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
sessionFactory = new SessionFactoryImpl(dataSource);
sessionFactory.setScanPackage("com.jfire.orm");//设置需要扫描的路径,在这个路径下使用注解的类会被自动发现。路径之间可以使用;号区隔
sessionFactory.init();使用给定的参数初始化
该方法会打开一个新的session
该方法会从当前的线程变量中获得session
SqlSession表示的一个数据库连接实例.其中包含了大部分的sql功能.这点观看代码很容易理解.
在使用SqlSession提供的查询接口中,框架具备将查询结果自动转换为对应的映射类的实例的能力。这样通过查询结果到类实例就变得自动化和透明。
SqlSession提供了类似HIbernate的类的CURD操作。对类的CURD操作就如果直接对表进行对象操作一样。比如插入一行数据就是调用session.save(entity)来完成。
将一个类与数据库表建立映射关系后,即可执行CURD操作或者是在查询语句中自动将数据库查询结果转换为对象实例。例子如下
@TableEntity(name = "user")//通过注解映射来表明该对象所映射的表.
public class User
{
@Id//表明该字段所对应的数据库字段为主键,在curd操作中,该注解是必须的
@Column(name = "userid")//表明该字段对应的数据库字段的名称,如果属性名和数据库字段名一致,则不需要该注解.
private Integer id;
@Column(name = "username")
private String name;
private String password;
private int age;
@OrmIgnore//使用该注解表明该字段不是数据库的映射字段
private String birthday;
}
如果一个类中有一个字段使用了Id注解表示主键,则该类可以通过SqlSession接口进行CURD操作。比如需要保存一行记录到数据库。可以构建一个User对象的实例,然后使用代码session.save(user)来完成。其中save会通过Id字段是否为空来判断是插入数据还是更新数据。
对于一个数据库表的CURD操作,等同于对类的执行相关操作。
增加一行数据到数据库,可以构建一个与该表映射的类的实例。如果数据库主键是自增,则可以使用session.save(entity)来完成插入的动作。否则就需要在类实例的id字段设置一个值,并且使用session.insert(entity)来将数据插入到数据库
更新一行数据,可以构建一个与该表映射的类的实例。并且注解了Id的字段要有值,该值与该行数据的主键相等。使用代码session.save(entity)来完成数据的更新。除了Id字段外,所有类中的字段的值都会被更新到数据库中
删除一行数据,只需要构建一个与该表映射的类的实例,并且将Id字段赋值。使用代码session.delete(entity)即可删除主键为id字段值的数据行
得到一行数据,只需要确定主键的值。通过代码session.get(EntityClass,id)就会返回entityClass的一个实例对象。
在Jfire-Orm框架中,最为常见和实际的使用是接口方法和sql语句的绑定.也就是通过定义一些接口方法,并且将接口方法和sql语句绑定,这样,程序中调用对应的方法就相当于发出sql语句。请见看下面的简单示例
public interface UserOp{
@query(sql="select * from user where id={id}",paramNames={"id"})
public User query(integer id);
}
public UserService{
public User find(integer id){
SqlSession session = sessionFactory.getCurrentSession();
//获取接口的实例,这个实例是框架自动生成的,每次获取都是一个新对象,同时该对象内使用了当前的session。所以如果session关闭,该实例不可继续进行操作
Userop userop = session.getMapper(Userop.Class);
return userop.query(id);
}
}
通过上面的代码可以很简单的看明白这个sql语句和方法的Orm是怎么使用的。简单的说步骤如下。
@Query,@Update,@BatchUpdate
在sql操作中,由于数据库名和字段名存在变化的可能性。为了减少这种变化对代码的影响,建议使用类名和属性名编写sql语句。框架会自动完成转换工作。
比如有一个映射类如下
@TableEntity(name="tb_user")
Class User
{
@Id
private Integer id;
@column(name="username") //数据库字段名是username
private String name;
}
以下的两个sql在最终使用的时候是等效的。因为框架会根据注解的内容自动将类名和属性名替换为注解中对应的数据库表名和字段名。其中类名的开始以@
表示,属性名的开始以^
表示。框架在解析sql语句时,会自动将这样标注的内容识别为类名和属性名从而进行转换。
比如select ^name from @User
会被框架转换成select username from tb_user
通过框架进行数据查询非常简单。下面是示例代码
public class UserOp
{
@Query(sql="select username from tb_user where userid = {id}",paramNames={"id"})
public String getUsernameById(int id)
@Query(sql="select username from tb_user where userid = {user.id}",paramNames={"user"})
public String getUsernameById(User user)
}
通过上面的代码,以userid
为查询条件,查询到username。并且返回。
查询使用的是Query
注解。包含两个属性,sql和paramNames。
sql属性是表明调用这个方法会发出的sql。sql中可以使用{}
作为参数占位符
{}
表示占位符,作用和jdbc编程中的?
作用相同。而{}
包围的字符串表示框架会使用这个字符串寻找到正确的方法入参设置到其中。
比如{id}
表示会将方法入参的参数id值设置到这个位置。{user.id}
表示会将方法入参中的对象user的id属性设置到这个位置。框架支持使用方法的入参诸如或者入参是个类的情况下,支持获取类中的属性值进行注入。
paramNames属性是一个String数组,用来表示方法入参的名称,顺序和方法入参一致
查询的结果,会自动转换为方法的返回对象类型。
比如查询的是tb_user表,其映射类为User。则方法的返回结果可以是
List<User>
,框架会自动将返回的每一行组装成一个User对象实例,并且最终以List的形式返回。如果确定返回的只有一行数据,方法的返回值类型也可以是User。在转换的时候,是将类中与查询结果字段名相同属性名或者其映射名的属性赋上对应的值来完成的。
如果返回的是普通的类型,也是支持的。比如返回值只有一行一列,是一个varchar类型,方法的返回类型就应该是String。
通过框架来进行数据更新也很简单。下面是示例代码
public class UserOp
{
@Update(sql="update @User set ^name = {name} where ^id = {id}",paramNames={"id","name"})
public void update(int id,String name);
@Update(sql="update @User set ^name = {name} where ^id = {id}",paramNames={"id","name"})
public int update2(int id,String name)
}
上面的代码中,注解Update
中的属性sql和paramNames的含义和Query
注解是相同的。升级方法的返回类型可以是void也可以是int。如果是int则返回的是这个更新语句对数据库的几条数据进行了改动。
jdbc编程之中,有些业务由于条件等原因需要手动的拼接sql再执行。最典型的就是条件查询中,条件为空和不为空sql语句不同。而这样给编程带来很多复杂性。故而Jfire-orm提供了切合实际需要的动态sql功能,专门用于解决这种情况。
在查询之中,很常见一种情况就是很多的查询条件,而且任意为空,这个时候大多数都需要程序员进行sql语句拼接,写出如下类似的代码
String sql = "select * from user where 1=1 "
if(age!=null){
sql +=" and age="+age;
}
if(name!=null){
sql +=" and name="+name;
}
如果这样的条件很多,则代码的可读性会变得很差,而且也会为编程带来负担。为了简化这种非空条件动态查询,Jfire-Orm支持条件判断。请看如下代码
@Query(sql = "select * from user where 1=1 "+
"[$user.age > 15] and age={user.age}#"+
"[$user.name] and username={user.name}# "+
"[$user.id] and userid={user.id}#", paramNames = { "user" })
public List<User> dynamicQuery(User user);
上面这段sql的含义是如果[]内的条件为假,则[]到#之间的内容不会出现在sql语句中。假设user.age=13,user.name为空,user.id有值。则sql会被框架转换为select * from user where 1=1 and userid = {user.id}
。
[]中使用$
来表示变量名的开始。如果[]内只有变量名,则默认是进行非空判断也就是!=null
。否则的话,就执行[]内的判断。[]内支持任意条件或者是条件组合。比如可以这样写[$user.name != null && user.age > 15 ]
在查询当中,有的时候会碰到类似select * from user where id in (?,?)
这种情况,如果参数的个数是不确定的,则只能手动拼接sql字符串。如果碰到这样的需求,jfire-orm支持自动的参数分解和拼接。举个例子,代码如下
/**
*ids为1,2,3,形式的字符串,框架会自动将逗号进行区隔,形成参数,然后以字符串的形式放入。
*/
select * from user where userid in ~{ids}
public List<User> list(String ids);
上面这个例子中,如果是ids的值为1,2,3,
则sql语句最终会被解析成select * from user where userid in (?,?,?)
不仅仅支持1,2,3这种形式。而且还直接支持数组等形式。如果给定的参数是一个数组或者经过参数运算返回的是一个数组,程序也能够将其进行拆分形成(?,?,?)这样的形式