文章目录
SpringJDBC
SpringJDBC是Spring对JDBC的封装,可以避免使用JDBC时的一些重复代码,如获取连接、关闭连接等操作。
一般步骤
1 导入maven依赖包
spring-webmvc,spring-jdbc, ojdbc,dbcp,junit
2 添加Spring配置文件,配置JdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds"/>
</bean>
3 调用JdbcTemplate的方法访问数据库
通常将JdbcTemplate注入到DAO中,方便使用。
实现一个基于spring-jdbc的增删改查实例。
package com.nc.springJdbc.DAO;
import com.nc.springJdbc.entity.Emp;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @ program: SpringJdbc
* @ description:
* @ create: 2020-08-20 14:37
**/
@Repository("empDAO")
public class EmpDAO {
@Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
public void save(Emp emp){
String sql = "INSERT INTO emp VALUES(emp_seq.nextval,?,?)";
Object[] params = new Object[]{emp.getName(), emp.getAge()};
jdbcTemplate.update(sql, params);
}
//告诉jdbcTemplate如何将ResultSet中的一条记录转换成对应的Entity对象。
class EmpRowMapper implements RowMapper<Emp> {
@Override
public Emp mapRow(ResultSet resultSet, int i) throws SQLException {
/**
* @Author: NiuChen
* @Date: 2020/8/20 15:34
* @param resultSet: 要处理的结果集
* @param i: 当前正在处理的记录的下标
* @return: com.nc.springJdbc.entity.Emp
**/
Emp emp = new Emp();
emp.setId(resultSet.getInt("id"));
emp.setName(resultSet.getString("name"));
emp.setAge(resultSet.getInt("age"));
return emp;
}
}
public List<Emp> findAll(){
List<Emp> emps = new ArrayList<Emp>();
String sql = "SELECT * FROM emp";
EmpRowMapper rowMapper = new EmpRowMapper();
emps = jdbcTemplate.query(sql, rowMapper);
return emps;
}
public Emp findById(int id){
Emp emp = null;
String sql = "SELECT * FROM emp WHERE id=?";
Object[] args = new Object[]{id};
// emp = jdbcTemplate.queryForObject(sql, args, new EmpRowMapper());
List<Emp> emps = jdbcTemplate.query(sql, args, new EmpRowMapper());
if (emps != null && emps.size() > 0){
emp = emps.get(0);
}
return emp;
}
public void modify(Emp emp){
String sql = "UPDATE emp SET name=?,age=? WHERE id=?";
Object[] args = new Object[]{emp.getName(), emp.getAge(), emp.getId()};
jdbcTemplate.update(sql, args);
}
public void delete(int id){
String sql = "DELETE FROM emp WHERE id=?";
Object[] args = new Object[]{id};
jdbcTemplate.update(sql, args);
}
}
MyBatis
MyBatis是一款开源的持久层框架,底层仍然是JDBC,性能比JDBC较弱一些,但是相较于JDBC代码更简洁。
一般步骤
1 导包
mybatis、ojdbc、junit
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
</dependencies>
2 添加配置文件SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="environment">
<environment id="environment">
<transactionManager type="JDBC" />
<!-- 配置数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521/orcl" />
<property name="username" value="nc" />
<property name="password" value="nc940306" />
</dataSource>
</environment>
</environments>
</configuration>
3 构建实体类
根据数据库字段构建自己的实体类,要求属性名和表字段名必须一致
public class Emp {
private Integer id;
private String name;
private Integer age;
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
4 写映射文件Mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="test">
<!-- parameterType参数类型 -->
<insert id="save" parameterType="com.niuchen.mybatis.entity.Emp">
INSERT INTO emp VALUES(emp_seq.nextval,#{name},#{age})
</insert>
<!-- resultType返回的数据类型 -->
<select id="findAll" resultType="com.niuchen.mybatis.entity.Emp">
SELECT * FROM emp
</select>
<select id="findById" parameterType="int" resultType="com.niuchen.mybatis.entity.Emp">
SELECT * FROM emp WHERE id=#{id}
</select>
<update id="modify" parameterType="com.niuchen.mybatis.entity.Emp">
UPDATE emp SET name=#{name}, age=#{age} WHERE id=#{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM emp WHERE id=#{id}
</delete>
<!-- 返回Map类型结果 -->
<select id="findById2" parameterType="int" resultType="map">
SELECT * FROM emp WHERE id=#{id}
</select>
<!-- 处理表字段名与实体属性名的对应关系
result把不一致的字段列举出来
-->
<!-- <select id="findById3" parameterType="int" resultMap="empMap">-->
<!-- SELECT * FROM emp WHERE id=#{id}-->
<!-- </select>-->
<!-- <resultMap id="empMap" type="com.niuchen.mybatis.entity.Emp">-->
<!-- <result property="ename" column="name"/>-->
<!-- <result property="empNo" column="id"/>-->
<!-- </resultMap>-->
</mapper>
完成后修改SqlMapConfig配置文件,指定映射文件的位置。
<!-- 映射文件位置 -->
<mappers>
<mapper resource="EmpMapper.xml"/>
</mappers>
5 调用mybatis SqlSession提供的方法访问数据库
import junit.framework.TestCase;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.Map;
public class testCase {
private SqlSession sqlSession;
@Before
public void init(){
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory =
sqlSessionFactoryBuilder.build(TestCase.class
.getClassLoader().getResourceAsStream("SqlMapConfig.xml"));
sqlSession= sqlSessionFactory.openSession();
}
@Test
public void test1(){
Emp emp = new Emp();
emp.setName("Eric");
emp.setAge(18);
sqlSession.insert("test.save", emp);
// 提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void test2(){
List<Emp> emps = sqlSession.selectList("test.findAll");
System.out.println(emps);
sqlSession.close();
}
@Test
public void test3(){
Emp emp = sqlSession.selectOne("test.findById", 21);
System.out.println(emp);
sqlSession.close();
}
@Test
public void test4(){
Emp emp = sqlSession.selectOne("test.findById", 21);
emp.setName("Moran");
emp.setAge(20);
sqlSession.update("test.modify", emp);
// 提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void test5(){
sqlSession.delete("test.delete", 21);
// 提交事务
sqlSession.commit();
sqlSession.close();
}
}
小知识
通常,mybatis会将查询结果先封装到一个Map对象,然后将Map对象中的数据添加到实体对象中。
我们也可以获取到Map对象,下面是获取方式:
如果实体类属性名与数据库表中字段名不一致,可以使用ResultMap解决或在映射文件中的写SQL语句时可以用别名。
<!-- 结果类型改为resultMap -->
<select id="findById3" parameterType="int" resultMap="empMap">
SELECT * FROM emp WHERE id=#{id}
</select>
<!-- 处理表字段名与实体属性名的对应关系
result把不一致的字段列举出来
-->
<resultMap id="empMap" type="com.niuchen.mybatis.entity.Emp">
<result property="ename" column="name"/>
<result property="empNo" column="id"/>
</resultMap>
获取Map类型数据
@Test
public void test6(){
Map data = sqlSession.selectOne("test.findById2", 22);
System.out.println(data);
System.out.println(data.get("NAME"));
sqlSession.close();
}
Google对MyBatis的改进
Mapper映射器
Mapper映射器是指符合映射文件要求的接口。
要求:
- a. 接口方法名称与映射文件的SQL的id要一致
- b. 方法的参数类型要与映射文件的parameterType一致
- c. 方法的返回值类型要与映射文件的resultType一致
- d. 映射文件的namespace必须与Mapper映射器的全限定名(包名、接口名)一致
以下给出简单示例:
EmpDAO .java
public interface EmpDAO {
public void save(Emp emp);
public List<Emp> findAll();
}
EmpDAOMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.niuchen.mybatis.dao.EmpDAO">
<!-- parameterType参数类型 -->
<insert id="save" parameterType="com.niuchen.mybatis.entity.Emp">
INSERT INTO emp VALUES(emp_seq.nextval,#{name},#{age})
</insert>
<!-- resultType返回的数据类型 -->
<select id="findAll" resultType="com.niuchen.mybatis.entity.Emp">
SELECT * FROM emp
</select>
<select id="findById" parameterType="int" resultType="com.niuchen.mybatis.entity.Emp">
SELECT * FROM emp WHERE id=#{id}
</select>
<update id="modify" parameterType="com.niuchen.mybatis.entity.Emp">
UPDATE emp SET name=#{name}, age=#{age} WHERE id=#{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM emp WHERE id=#{id}
</delete>
<!-- 返回Map类型结果 -->
<select id="findById2" parameterType="int" resultType="map">
SELECT * FROM emp WHERE id=#{id}
</select>
<!-- 处理表字段名与实体属性名的对应关系
result把不一致的字段列举出来
-->
<!-- <select id="findById3" parameterType="int" resultMap="empMap">-->
<!-- SELECT * FROM emp WHERE id=#{id}-->
<!-- </select>-->
<!-- <resultMap id="empMap" type="com.niuchen.mybatis.entity.Emp">-->
<!-- <result property="ename" column="name"/>-->
<!-- <result property="empNo" column="id"/>-->
<!-- </resultMap>-->
</mapper>
测试
@Test
public void test7(){
EmpDAO dao = sqlSession.getMapper(EmpDAO.class);
Emp emp = new Emp();
emp.setName("Lily");
emp.setAge(22);
dao.save(emp);
sqlSession.commit();
sqlSession.close();
}
MyBatis会自动实现一个符合该接口要求的对象。