前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你还在用传统的 JDBC 持久化访问吗

你还在用传统的 JDBC 持久化访问吗

作者头像
技术zhai
发布2019-02-28 17:15:42
5720
发布2019-02-28 17:15:42
举报
文章被收录于专栏:JAVA技术zhaiJAVA技术zhai

前言

这里我会采用mybatis3.2做数据库的持久化,很多小伙伴或许还停留在老师的教导下,仍然停留在使用传统的JDBC持久化访问数据层。今天,我们来聊聊面向接口编程和怎么充分利用注解的优势!

实现DAO持久层

从目前的Java框架趋势来看,spring框架仍旧占据主流,不论你使用SSH框架和SSM框架开发,必透彻spring是无可厚非的。

从目前互联网公司的分布来看,中小型公司仍旧拥有半壁江山,它们没有雄厚的资金和开发资源,也就是说极少有公司会使用hibernate+struts开发项目,对中小型公司来说开发超大型项目是不在它们的考虑范围之内的。那么,mybatis+springmvc开发框架就此兴起…

闲聊结束,我先说说原理吧:

使用mybatis定义接口完成sql语句的映射,该接口还可以直接作为DAO的组件使用。

桥接模式知道吗?

桥接模式在这里的应用:

使用该模式能够体现业务逻辑组件封装DAO组件的模式,也可以分离业务逻辑组件和DAO组件的功能。也就是说,业务逻辑组件负责业务逻辑的变化,而DAO组件负责持久化的变化。

这样做的好处: ①每个DAO组件包含了数据库的访问逻辑。 ②每个DAO组件可对一个数据表完成基本的CRUD等操作。

1.公共常量类

HrmConstants 类

1234567891011121314151617181920212223

/** *  * 常量 * */public class HrmConstants {     //数据库表常量    public static final String USERTABLE="user_inf";    public static final String DEPTTABLE="dept_inf";    public static final String JOBTABLE="job_inf";    public static final String EMPLOYEETABLE="employee_inf";    public static final String NOTICETABLE="notice_inf";    public static final String DOCUMENTTABLE="document_inf";         //登录    public static final String LOGIN="loginFrom";    //用户的session对象    public static final String USER_SESSION="user_session";    //默认每页4条数据    public static int PAGE_DEFAULT_SIZE=4;     }

这里数据库我就不贴出来了。这个公共常量类根据数据库表的结构定义得,也就是说在数据库里面我一共创建了6个表,每个表和此类是一一对应的。至于这里的session对象,是为了后期编写控制层所铺垫的,与本次所讲内容无影响噢。

2.实体类

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

/** *  * 用户实体类 * */public class User {     private Integer id;//id    private String username;//用户名    private String loginname;//登录名    private String password;//密码    private Integer status;//状态    private Date createDate;//建档日期         public User() {    }     //setter和getter方法    public Integer getId() {        return id;    }     public void setId(Integer id) {        this.id = id;    }     public String getUsername() {        return username;    }     public void setUsername(String username) {        this.username = username;    }     public String getLoginname() {        return loginname;    }     public void setLoginname(String loginname) {        this.loginname = loginname;    }     public String getPassword() {        return password;    }     public void setPassword(String password) {        this.password = password;    }     public Integer getStatus() {        return status;    }     public void setStatus(Integer status) {        this.status = status;    }     public Date getCreateDate() {        return createDate;    }     public void setCreateDate(Date createDate) {        this.createDate = createDate;    }     }

这里,我会以用户实体类做一个案例介绍。实体类的基本准则就是遵循javabean规则,也就是常说的公有的类、私有的成员变量以及自带一个无参的构造方法。当然,这里我用了setter和getter方法对其进行了简单的封装。

3.定义DAO接口

123456789101112131415161718192021222324252627282930313233343536373839

/** *  * UserDao的接口实现类 * */public interface UserDao {     //登录用户名和密码查询员工    @Select("select * from "+USERTABLE+" where loginname = #{loginname} and password = #{password} ")    User selectByLoginnmameAndPassword(            @Param("loginname") String loginname,            @Param("password") String password            );         //根据Id查询用户    @Select("select * from "+USERTABLE+" where id = #{id} ")    User selectById(Integer id);         //根据Id删除用户    @Delete("delete from "+USERTABLE+" where id = #{id} ")    void deleteById(Integer id);         //动态修改用户    @SelectProvider(method = "updateUser", type = UserDynaSqlProvider.class)    void update(User user);         //动态查询    @SelectProvider(method = "selectWhitParam", type = UserDynaSqlProvider.class)    List<User> selectByPage(Map<String, Object> params);         //根据参数查询用户总数    @SelectProvider(method = "count", type = UserDynaSqlProvider.class)    Integer count(Map<String, Object> params);         //动态插入用户    @SelectProvider(method = "inserUser", type = UserDynaSqlProvider.class)    void save(User user);     }

这里才是真正的开始升华了,首先我只定义了一个 UserDao的接口,然后充分利用mybatis的注解优势,定义了’登录用户名和密码查询员工’的方法……

这里为大家补充一下注解知识:

@Select注解,这个不用解释了吧,就相当于存放查询语句的一个注解,定义在某一个方法上,效果相当于在配置文件里面编写查询语句。

@Param注解,是对参数的解释。这里用的 string loginname是前面在公共常量类里面定义的。怎么说呢,我们可以理解成request.setAttribute(“”,”")这种形式的升华吧。

@SelectProvider注解,用于生成查询用的sql语句,有别于@Select注解。结构上看,@SelectProvide指定了一个Class及其方法,通过调用Class上的这个方法来获得sql语句。

注意事项:

①这里的@Param注解是基于mybatis框架的,不是spring框架上的,导入包的时候要注意哟! ②@SelectProvider注解在编程的思维上有一个跨度,因为它本身需要一个class和其方法,所以在定义这个注解的时候,务必思考好下一个层次结构里面的类和方法所需要做的事哦!当然,在接口里面的方法,是可以事先预算好的,但是在它上面的注解,就要多思考思考才能做决定哦! ③公共常量类。在此接口的运用上,既然是面向接口编程,还要完成数据库的基本操作,那么是一定要导入公共常量类里面的USERTABLE的。 ④id = #{id} 生成的sql语句是 id = ?

4.动态SQL提供类

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990

public class UserDynaSqlProvider {     //分页动态查询    public String selectWhitParam(final Map<String, Object> params) {        String sql=new SQL(){            {                SELECT("*");                FROM(USERTABLE);                if (params.get("user")!=null) {                    User user=(User) params.get("user");                    if (user.getUsername()!=null && !user.getUsername().equals("")) {                        WHERE(" username LIKE CONCAT('%',#{user.username},'%') ");                    }                    if (user.getStatus()!=null && !user.getStatus().equals("")) {                        WHERE(" status LIKE CONCAT('%',#{user.status},'%') ");                    }                }            }        }.toString();        if (params.get("pageModel")!=null) {            sql += " limit #{pageModel.firstLimitParam} , #{pageModel.pageSize} ";        }        return sql;    }         //动态查询总数量    public String count(final Map<String, Object> params) {        return new SQL(){            {                SELECT("*");                FROM(USERTABLE);                if (params.get("user") !=null) {                    User user=(User) params.get("user");                    if (user.getUsername()!=null && !user.getUsername().equals("")) {                        WHERE(" username LIKE CONCAT('%',#{user.username},'%') ");                    }                    if (user.getStatus()!=null && !user.getStatus().equals("")) {                        WHERE(" status LIKE CONCAT('%',#{user.status},'%') ");                    }                }            }        }.toString();    }         //动态插入    public String inserUser(final User user) {        return new SQL(){            {                INSERT_INTO(USERTABLE);                if (user.getUsername()!=null && !user.getUsername().equals("")) {                    VALUES("username", "#{username}");                }                if (user.getStatus()!=null && !user.getStatus().equals("")) {                    VALUES("status", "#{status}");                }                if (user.getLoginname()!=null && !user.getLoginname().equals("")) {                    VALUES("loginname", "#{loginname}");                }                if (user.getPassword()!=null && !user.getPassword().equals("")) {                    VALUES("password", "#{password}");                }            }        }.toString();    }         //动态更新    public String updateUser(final User user) {        return new SQL(){            {                UPDATE(USERTABLE);                if (user.getUsername()!=null) {                    SET(" username = #{username} ");                }                if (user.getLoginname()!=null) {                    SET(" loginname = #{loginname} ");                }                if (user.getPassword()!=null) {                    SET(" password = #{password} ");                }                if (user.getStatus()!=null) {                    SET(" status = #{status} ");                }                if (user.getCreateDate()!=null) {                    SET(" create_date = #{createDate} ");                }                WHERE(" id = #{id} ");            }        }.toString();    }}

正如前面编写接口类的时候所说,既然用了@SelectProvider注解,必然会使用到一个class和它的方法。我们在接口类里面用了四次@SelectProvider注解,那么与之对应的就应该有四个方法,分别是分页动态查询(selectWhitParam)、动态查询总数量(count)、动态插入(inserUser)、动态更新(updateUser)。

这个类是专门为接口提供sql语句服务的,不再需要传统的去实现接口,用注解代替了原本繁琐的事情。

ps:或许有人会疑惑,我们怎么把所写的配置在applicationContext.xml里面呢?会不会很麻烦?现在,我告诉你,一点也不麻烦哦!

配置文件

applicationContext.xml

12345678

<!-- mybatis:scan 会扫描com.dao.inter包下面的所有接口当作spring的bean配置,之后可以进行依赖注入 -->    <mybatis:scan base-package="com.dao.inter"/>    <!-- 使用PropertyOverrideConfigurer后处理器加载数据源参数 -->    <context:property-override location="classpath:db.properties" />    <!-- 配置c3p0数据源 -->    <bean id="dataSource" class="com.mchange.v2.c3p0.CombopooledDataSource "/>    <!-- 配置sqlSessionFactory。org.mybatis.spring.SqlSessionFactoryBean是mybatis社区开发用于整合Spring的bean -->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource"/>

db.properties

12345678

dataSource.driverClass=com.mysql.jdbc.DriverdataSource.jdbcUrl=jdbc:mysql://127.0.0.1:3306/hrm_dbdataSource.user=rootdataSource.password=rootdataSource.maxPoolSize=20dataSource.maxIdleTime=1000dataSource.minPoolSize=6dataSource.initialPoolSize=5

原理:mybatis的持久化DAO接口只需要通过SqlSession的getMapper方法获得对应的接口实例,从而达到调用接口方法完成数据库的操作,而在spring容器里,只负责生成和管理DAO的组件。

看完了?那么大家觉得是不是要比传统的JDBC持久化访问要简单些呢?我想,至少也要方便一些吧。

如果你也想在IT行业拿高薪,可以参加我们的训练营课程,选择最适合自己的课程学习,技术大牛亲授,7个月后,进入名企拿高薪。我们的课程内容有:Java工程化、高性能及分布式、高性能、深入浅出。高架构。性能调优、Spring,MyBatis,Netty源码分析和大数据等多个知识点。如果你想拿高薪的,想学习的,想就业前景好的,想跟别人竞争能取得优势的,想进阿里面试但担心面试不过的,你都可以来,群号为: 650385180 注:加群要求 1、具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加。 2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加。 3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加。 4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。 5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知! 6.小号或者小白之类加群一律不给过,谢谢。 目标已经有了,下面就看行动了!记住:学习永远是自己的事情,你不学时间也不会多,你学了有时候却能够使用自己学到的知识换得更多自由自在的美好时光!时间是生命的基本组成部分,也是万物存在的根本尺度,我们的时间在那里我们的生活就在那里!我们价值也将在那里提升或消弭!Java程序员,加油吧

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年02月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现DAO持久层
  • 1.公共常量类
  • 2.实体类
  • 3.定义DAO接口
    • 注意事项:
    • 4.动态SQL提供类
    • 配置文件
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档