发表于: 2019-10-20 22:31:27

2 1000


今天完成的事情:

1、JdbcTemplate 实现 DAO

JDBCTemplate 是 Spring 中关于 JDBC 的一个辅助类,对 JDBC 的操作进行了封装。首先在 Maven 中添加对 Spring-JDBC 和 MySQL 驱动的依赖

<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>8.0.17</version>
</dependency>

<dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <version>0.9.1.2</version>
</dependency>


声明接口 StudentService:

public interface StudentService {
List<Student> queryById(long id);

   long insertInfo(Student student);

   boolean deleteById(long id);

   boolean updateSloganById(String slogan, long id);
}

创建 StudentDaoImpl 实现 StudentDao 接口

public class StudentServiceImpl implements StudentService {

private JdbcTemplate jdbcTemplate;

   public JdbcTemplate getJdbcTemplate() {
      return jdbcTemplate;
   }

   public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
      this.jdbcTemplate = jdbcTemplate;
   }

   @Override
   public List<Student> queryById(long id) {
               String sql = "SELECT id,create_time,update_time,name,qq,jnshu_type,join_time,school,online_num,                               daily_url,slogan,counsellor,known_path FROM student WHERE id = ?";
              List<Student> student = jdbcTemplate.query(sql, new StudentMapper(), id);
       return student;
   }

   @Override
   public long insertInfo(final Student student) {

         final String sql = "

                           INSERT INTO student(name,qq,jnshu_type,join_time,school,online_num,daily_url,sloga                             n,counselor,know_path) " +"VALUES (?,?,?,?,?,?,?,?,?,?)";

       //long createAt = student.getCreate_at();
       //long updateAt = student.getUpdate_at();

       KeyHolder keyHolder = new GeneratedKeyHolder();
       jdbcTemplate.update(new PreparedStatementCreator() {

       public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
               String name = student.getName();
               String qq = student.getQq();
               String profession = student.getJnshuType();
               String joinAt = student.getJoinTime();
               String dailyUrl = student.getDailyUrl();
               String onlineNum = student.getOnlineNum();
               String counselor = student.getCounsellor();
               String school = student.getSchool();
               String slogan = student.getSlogan();
               String knowPath = student.getKnownPath();

               PreparedStatement preState = con.prepareStatement(sql);
               preState.setString(1, name);
               preState.setString(2, qq);
               preState.setString(3, profession);
               preState.setString(4, joinAt);
               preState.setString(5, dailyUrl);
               preState.setString(6, onlineNum);
               preState.setString(7, counselor);
               preState.setString(8, school);
               preState.setString(9, slogan);
               preState.setString(10, knowPath);
               return preState;
             }

           },keyHolder);
       return keyHolder.getKey().longValue();

   }

   //省略部分源代码

//
}


为 JdbcTemplate 配置数据源,这里使用 c3p0 ,添加相应的 Maven 依赖

<dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <version>0.9.1.2</version>
</dependency>

获取 JdbcTemplate 实例

public JdbcTemplate getJdbcTemplate()throws PropertyVetoException{
JdbcTemplate jdbcTemplate = new JdbcTemplate();
   ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
   comboPooledDataSource.setUser("root");
   comboPooledDataSource.setPassword("zhou1990");
   comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
   comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jnshu?useUnicode=true&characterEncoding=UTF-8");
   jdbcTemplate.setDataSource(comboPooledDataSource);
   return jdbcTemplate;
}

执行 StudentService 的 查询方法:

public void queryStudent() throws PropertyVetoException {
StudentServiceImpl studentService = new StudentServiceImpl();

   studentService.setJdbcTemplate(getJdbcTemplate());
   Student student = studentService.queryById(6).get(0);
   System.out.println("student info---->"+student.toString());
}

查询出数据库结果为:

2、Mybatis 实现 DAO

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。

配置 MyBatis & MySql 驱动 的Maven 依赖

<dependency>
 <groupId>org.mybatis</groupId>
 <artifactId>mybatis</artifactId>
 <version>3.4.6</version>
</dependency>

配置 Mybatis Configuration 其中包含了 数据库连接池、事务管理等 以及 mapper(Sql 映射文件) 的注册

<configuration>
   <properties resource="db.properties"/>
   <!-- 开启驼峰映射 ,为自定义的SQL语句服务-->
   <!--设置启用数据库字段下划线映射到java对象的驼峰式命名属性,默认为false-->
   <settings>
       <setting name="mapUnderscoreToCamelCase" value="true"/>
   </settings>

   <environments default="development">
       <environment id="development">
           <!-- 使用jdbc事务管理,事务控制由mybatis-->
           <transactionManager type="JDBC"/>
           <!-- 数据库连接池,由mybatis管理-->
           <dataSource type="POOLED">
               <property name="username" value="${username}"></property>
               <property name="password" value="${password}"></property>
               <property name="url" value="${url}"></property>
               <property name="driver" value="${driver}"></property>
           </dataSource>
       </environment>
   </environments>
   <mappers>
       <mapper resource="mappers/StudentMapper.xml"/>
   </mappers>
</configuration>

编写 Mapper 配置文件 StudentMapper.xml

<mapper namespace="com.gerry.jnshu.mapper.StudentMapper">

   <!--<resultMap id="studentRM" type="com.gary.mavenmybatis.entity.Student">-->
       <!--<id property="id" column="id"/>-->
       <!--<result property="name" column="name"/>-->
       <!--<result property="qq" column="qq"/>-->
   <!--</resultMap>-->
   <select id="queryStudentById" parameterType="long" resultType="com.gerry.jnshu.bean.Student">
       SELECT * FROM student WHERE id = #{id}
   </select>

   <insert id="insertStudentInfo" useGeneratedKeys="true" keyProperty="id" parameterType="com.gerry.jnshu.bean. Student">
     INSERT INTO student(name,qq,jnshu_type,join_time,school,online_num,daily_url,slogan,counselor,know_path)
      VALUES (#{name},#{qq},#{profession},#{joinTime},#{school},#{onlineNum},#{dailyUrl},#{slogan},#{counsello        r},#{knownPath})
  </insert>

   <update id="updateSloganById">
      UPDATE student SET slogan = #{param1} WHERE ID = #{param2}

   </update>

   <delete id="deleteStudentById" parameterType="long">
       DELETE FROM student WHERE id = #{id}
   </delete>
</mapper>

用传统方式实现 Dao,声明接口如上 StudentService,编写实现类:StudetnServiceImpl2

public class StudentServiceImpl2 implements StudentService {
private MyBatisUtil myBatisUtil;

   public StudentServiceImpl2() {
     this.myBatisUtil = new MyBatisUtil();
   }

    public List<Student> queryById(long id) {

       SqlSession sqlSession = myBatisUtil.getSqlSession();
       List<Student> studentInfos = sqlSession.selectList("com.gerry.jnshu.mapper.StudentMapper.queryStudentById", id);
       sqlSession.close();
       return studentInfos;
   }

   public long insertInfo(Student student) {
       SqlSession sqlSession = myBatisUtil.getSqlSession();
       sqlSession.insert("com.gerry.jnshu.mapper.StudentMapper.insertStudentInfo",student);
       sqlSession.commit();
       sqlSession.close();
       return student.getId();
   }
   //省略部分源码

}

MyBatisUtil 管理 SessionFactory 和 Session 的类

public class MyBatisUtil {

private SqlSessionFactory sessionFactory;

   public MyBatisUtil() {
       String resource = "mybatis/MybatisConfig.xml";
       try {
           InputStream inputStream = Resources.getResourceAsStream(resource);
           //创建会话工厂,传入mybatis配置文件的信息
           sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
       } catch (IOException e) {
            e.printStackTrace();
       }
}

   public SqlSession getSqlSession() {
      return sessionFactory.openSession();
   }
}

传统的Dao 接口实现类方法中存在了大量的模板方法,为了简化开发者工作,接下来将介绍 MyBatis 最常用的 mapper 代理方法(接口式编程)。

开发过程中只需定义 mapper 接口,那么 我们之前编写的 mapper.xml 映射文件相当于 mapper 接口的实现。

这个过程中需要遵循以下规范:

  1. xxxMapper.java 接口中定义的方法名应该和 xxxMapper.xml 文件中的 statement id 保持一致

  2. xxxMapper.java 接口中的方法输入参数类型和 xxxMapper.xml 中 statement 的 parameterType 指定的类型一致。

  3. xxxMapper.java 接口中的方法返回值类型和 xxxMapper.xml 中 statement 的 resultType 指定的类型一致。

  4. xxxMapper.xml 文件中的 namespace 应该指向 xxxMapper.java 接口的全路径

此时我们定义的接口与 xml配置文件产生了绑定。那么具体实现类就是由 MyBatis 创建代理对象去执行对应的方法,接口规范 和 DAO 层实现了分离。

首先定义 StudentMapper 接口

public interface StudentMapper {

List<Student> queryStudentById(long id);
    long insertStudentInfo(Student student);
    boolean deleteStudentById(long id);
    boolean updateSloganById(String slogan, long id);

}

然后通过 SqlSessionFactory 创建的 sqlSession 实例获取 StudentMapper 实例对象

public void queryStudent2() throws PropertyVetoException {
StudentServiceImpl2 studentService = new StudentServiceImpl2();

   Student student = studentService.queryById(6).get(0);
   System.out.println(student.toString());
   MyBatisUtil myBatisUtil = new MyBatisUtil();
   SqlSession sqlSession = myBatisUtil.getSqlSession();
   StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
   List<Student> studentInfos= studentMapper.queryStudentById(6);
   System.out.println("studnetInfos size---->"+studentInfos.size());
   System.out.println("student info--->"+student);
}

执行结果如下:

Mybaits 除了用 xml 配置外,还可以使用注解的形式

public interface StudentMapperAnnotation {

@Select("SELECT * FROM student WHERE id = #{id}")
List<Student> queryStudentById(long id);

   @Insert("INSERT INTO student(name,qq,jnshu_type,join_time,school,online_num,daily_url,slogan,counselor,known_path)" +
"VALUES (#{name},#{qq},#{jnshuType},#{joinTime},#{school},#{onlineNum},#{dailyUrl},#{slogan},#{counsellor},#{knownPath})")
long insertStudentInfo(Student student);

   @Update("UPDATE student SET slogan = #{param1} WHERE ID = #{param2}")
int deleteStudentById(long id);

   @Delete("DELETE FROM student WHERE  id = #{id}")
int updateSloganById(String slogan, long id);

}

直接将 sql 语句标注在对应的方法上即可。但是觉得这种方式不便于维护(尤其是 sql 比较 复杂的情况),所以还是推荐 xml 文件的形式进行操作。

明天计划的事情:(一定要写非常细致的内容)

3、关于深度思考的问题

1)Mybatis有哪些常用标签?怎么使用标签来完成动态查询?(学习了小课堂的知识)

Mybatis 常用的标签

定义 sql 语句 :select、insert、update、delete

配置 结果集映射:resultMap

动态 SQL 拼接:if foreach choose

格式化输出 where set trim

配置关联关系 collection assocication

定义常量及引用 sql include

if 标签:简单的条件判断,利用 if 语句我们可以实现某些简单的条件选择,一般用于动态选项的查询,选项值有可能为空,因此需要用到动态 if 标签来判断             

 <select id="find" parameterType="Admin" resultType="Admin">

         select * from admin where 1=1 

         <if test="age!= null and age!='' ">

              and age=#{age}

          </if>

          <if test="city!= null and city!='' ">

               and city=#{city}

           </if>

 </select>

注意:上面的 “1=1”始终为 true,所以后面可以直接接 and 语句,不然就会出现“where and age=#{age}”这样的错误。


where 标签:补充相应的 where 的 sql 语句,解决了 if 标签在上面容易造成的错误,简化了 where 子句的拼接

<select id="find" parameterType="Admin" resultType="Admin">

        select * from admin

    <where>

        <if test="age!= null and age!='' ">

                and age=age

        </if>

        <if test="city!= null and city!='' ">

                and city=city

        </if>

    </where>

</select>

这里就不需要再补充“1=1”的语句了,这是因为where标签会自动帮你处理,如果where后边是and,or开头的会被自动忽略掉。如果使用了and,or的话,mybatis也会自动为你在前后补充空格,不用担心出现“ageandpassword”的错误出现

choose标签:相当于 switch 语句,通常与 when otherwise 搭配使用

<select id="find" parameterType="Admin" resultType="Admin">

    select * from admin where 1=1

    <choose>

        <when test="age!= null and age!=''">

            and age=#{age}

        </when>

        <when test="city!= nulland city!=''">

            and city=#{city}

        </when>

        <otherwise>

             and aname=#{aname}

        </otherwise>

    <choose>

<select>

这里不会每一条都执行,类似于switch case语句。从上往下执行,当when中有条件满足的时候,就会跳出choose。when中条件都不执行则会执行otherwise语句。即最终choose里面仅有一条语句执行。

Set 标签:类似于 where 功能,主要用于 sql 更新赋值操作

<update id ="update" parameterType="Admin">

    update admin

    <set>

         <if test="aname !=null and aname !='' ">

                aname=#{aname},

        </if>

        <if test="age!= null and age!='' ">

                age=#{age},

        </if>

        <if test="city!= null and city!='' ">

                password=#{password},

        </if>

    </set>

    where aid=#{aid}

</update>

set 标签会自动忽略不必要的后缀逗号


foreach标签:类似于for循环,循环的对象可以是list和数组。时常用于sql的批量操作,如批量删除,批量添加数据等。

批量添加用户

<insert id="addAdmin" >

        insert into amdin

        (aid,aname,pwd,city,address)

        values

        <foreach collection="list" item="item" index="index" separator=",">  

            (#{item.aid},#{item.aname},#{item.pwd},#{item.city},#{item.address)       

        </foreach>  

</insert>

与之相应的sql语句为:insert into admin (…) values(…);。foreach就将对象一个个存入数据库中


批量删除用户

<delete id="delAdmin">

     delete from admin where aid in

     <foreach collection="array" item="aid" open="(" separator=","  close=")">

           #{aid}

     </foreach>

</delete>

相应的语句为:delete from admin where aid into(…);。foreach会将数组转为(aid,aid,aid)的形式,主要看foreach的后三个属性就可知道


trim 标签:功能十分强大,常用的属性 prefix、suffix。同时提供了 prefixOverides、suffixOverirdes 来覆盖首尾部的内容,及忽略不要的前后缀

例如:

<trim prefix = "where" prefixOverrides="and|or" >

    ...

</trim>

可以充当 where 标签

<trim prefix="set" suffixOverrides=",">

    ...

</trim>

可以充当 set 标签


动态添加用户

<insert id="find" resultType="user">

    insert into admin 

    <trim prefix="(" suffix=")" suffixOverrides=",">

        <if test = "aname != null and aname !='' ">

            aname,

        </if>

        <if test = "city != null and city !='' ">

            city,

        </if>

        <if test = "age != null and age !='' ">

            age,

        </if>

    </trim>

    <trim prefix="values(" suffix=")" suffixOverrides=",">

        <if test = "aname != null and aname !='' ">

            #{aname},

        </if>

        <if test = "city != null and city !='' ">

            #{city},

        </if>

        <if test = "age != null and age !='' ">

            #{age},

        </if>

    </trim>

</insert>

生成相应的 sql 语句为 insert into user (…) values(…);


2)JDBCTemplate和JDBC (学习小课堂知识)

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API, 可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

JDBC的具体步骤

1、注册载入JDBC驱动程序

2、得到连接对象 Connection

3、创建 Statement对象

4、运行sql语句

5、处理结果

6、关闭资源释放资源

JdbcTemplate 就是 Spring 对 jdbc 的封装的模板, Spring 对数据库的操作在 jdbc 上面做了深层次的封装,使用 spring 的注入功能,可以把 DataSource 注入到 JdbcTemplate 之中.

那么为什么要对 JDBC 进行封装

使用原生jdbc的时候,总是需要与数据库建立连接,在使用完毕后释放它。 但是数据库连接是十分有限的资源,对此进行管理能显著影响整个应用程序的的性能,于是提出了数据库连接池。 

数据库连接池本质上是,在整个系统初始化的时候,把设定好的数据库连接建立、存储在内存中, 用户需要访问数据库的时候就从中取出一个空闲的连接,使用完毕后也只是把连接重新放回连接池中,留待下一个请求使用 , 而不是关闭这个连接。

那么 JdbcTemplate 则为我们提供了更好的操作数据库的方式,处理了资源的建立和释放。帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如 Statement 的建立和执行,而我们只需要提供SQL语句和提取结果。


3)为什么要使用Interface,而不是直接使用一个实体类来完成任务?Interface和Impl这种方式的好处是什么? 

接口的作用有很多,比如

1.重要性 在java中,abstract class 和 interface 是支持抽象类定义的两种机制。赋予了Java面向对象的能力。

2.简单、规范性。大型项目,通过定义接口可以告诉开发人员需要实现的业务,同时限制了命名规范。

3.维护、扩展性。接口定义了功能,然后通过定义类来实现功能。这样需要使用接口的功能时就是使用这个接口去引用实现它的类。这样当接口功能需要更新时,对应功能上来讲,只需要更换引用的实现类。

4.安全、严密性。接口是实现软件松耦合的重要手段,它描述了系统对外的所有服务,而不涉及任何具体的实现细节。


接下来的计划:

1、Junit 和 Log 的使用

2、Spring 的学习,及与 Mybatis 的整合


遇到的问题:

暂时没有遇到大的问题,动态 sql 语句还是欠缺练习,以后在项目中慢慢巩固吧,继续加油


收获:

学习了  JBDCTemplate 与 Mybatis 对 DAO 层的基本实现。了解了 Mybatis 的基本配置及动态 sql 标签的使用。


返回列表 返回列表
评论

    分享到