发表于: 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 接口的实现。
这个过程中需要遵循以下规范:
xxxMapper.java 接口中定义的方法名应该和 xxxMapper.xml 文件中的 statement id 保持一致
xxxMapper.java 接口中的方法输入参数类型和 xxxMapper.xml 中 statement 的 parameterType 指定的类型一致。
xxxMapper.java 接口中的方法返回值类型和 xxxMapper.xml 中 statement 的 resultType 指定的类型一致。
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 标签的使用。
评论