无论选择Spring的哪种数据访问方式,你都需要配置一个数据源的引用。Spring提供了在Spring上下文中配置数据源bean的多种方式,包括:
使用Java配置的话,我们可以借助JndiObjectFactoryBean中查找DataSource:
@Bean
public DataSource productionDataSource(){
//使用JNDI数据源
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("org.h2.Driver");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}
使用Java配置,借助BasicDataSource类的bean声明如下:
@Bean
public DataSource quDataSource(){
//数据源连接池
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("org.h2.Driver");
basicDataSource.setUrl("jdbc:h2:tcp://localhost/~/spitter");
basicDataSource.setUsername("sa");
basicDataSource.setPassword("");
return basicDataSource;
}
在Spring中,通过JDBC驱动定义数据源是最简单的配置方式。Spring提供了三个这样的数据源类供选择:
注意:SingleConnectionDataSource有且只有一个数据库连接,不适于多线程,DriverManagerDataSource和SimpleDriverDataSource尽管支持多线程,但是在每次请求的时候都会创建新连接,这是以性能为代价的。
使用Java配置,借助DriverManagerDataSource类的bean声明:
//基于JDBC驱动的数据源
@Bean
public DataSource jdbcDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:tcp://localhost/~/spitter");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
使用Java配置,借助EmbeddedDatabaseBuilder类的bean声明:
@Bean
public DataSource developmentDataSource(){
//嵌入式数据原:每次重启应用或运行测试的时候,都能够重新填充测试数据
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
生产开发环境建议在数据源连接池和JNDI数据源中做选择,测试环境选择JDBC数据源或者嵌入式数据库。
使用JDBC能够更好地对数据访问的性能进行调优。JDBC允许你使用数据库的所有特性,而这是其它框架不支持甚至禁止的。再者,相对于持久层框架,JDBC能够让我们在更低的层次上处理数据,我们可以完全控制应用程序如何读取和管理数据,包括访问和管理数据库中单独的列。这种细粒度的数据访问方式在很多应用程序中是很方便的。
直接使用JDBC代码示例:
@Component
public class TestDaoImpl implements TestDao {
@Autowired
private DataSource dataSource;
private static final String SQL_INSERT_TEST = "insert into test (user_name) values (?)";
private static final String SQL_UPDATE_TEST = "update test set user_name = ? where id = ?";
private static final String SQL_CHECK_TEST = "select id,user_name from test where id = ?";
@Override
public void addTest(Test test) {
Connection conn = null;
PreparedStatement stmt = null;
try{
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_INSERT_TEST);
stmt.setString(1, test.getUserNme());
stmt.execute();
}catch(SQLException e){
e.printStackTrace();
}finally {
try{
if(stmt != null){
stmt.close();
}
if(conn != null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
@Override
public void updateTest(Test test) {
Connection conn = null;
PreparedStatement stmt = null;
try{
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_UPDATE_TEST);
stmt.setString(1, test.getUserNme());
stmt.setInt(2, test.getId());
stmt.execute();
}catch(SQLException e){
e.printStackTrace();
}finally {
try{
if(stmt != null){
stmt.close();
}
if(conn != null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
@Override
public Test checkTest(int id) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
conn = dataSource.getConnection();
stmt = conn.prepareStatement(SQL_CHECK_TEST);
stmt.setInt(1, id);
rs = stmt.executeQuery();
Test test = null;
if(rs.next()){
test = new Test();
test.setId(rs.getInt("id"));
test.setUserNme(rs.getString("user_name"));
}
return test;
}catch(SQLException e){
e.printStackTrace();
}finally {
try{
if(stmt != null){
stmt.close();
}
if(conn != null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
return null;
}
}
使用JdbcTemplate来读取数据:
@Component
public class DbUserDaoImpl implements DbUserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
private static final String SQL_INSERT_DBUSER = "insert into user_list (username, mobile, cardnumber) values (?, ?, ?)";
private static final String SQL_CHECK_DBUSER = "select id,username,mobile,cardnumber from user_list";
private static final String SQL_FINDBYID_DBUSER = "select id,username,mobile,cardnumber from user_list where id = ?";
private static final String SQL_UPDATE_DBUSER = "update user_list set username = ?,mobile = ?,cardnumber = ? where id = ?";
@Override
public void addDbUser(DbUser dbUser) {
jdbcTemplate.update(SQL_INSERT_DBUSER, dbUser.getUsername(), dbUser.getMobile(), dbUser.getCardnumber());
}
@Override
public List findAll() {
return jdbcTemplate.query(SQL_CHECK_DBUSER, new DbUserRowMapper());
}
@Override
public DbUser findById(int id) {
return jdbcTemplate.queryForObject(SQL_FINDBYID_DBUSER, new DbUserRowMapper(), id);
}
public static final class DbUserRowMapper implements RowMapper<DbUser>{
public DbUser mapRow(ResultSet rs, int rowNum) throws SQLException {
int id = rs.getInt("id");
String username = rs.getString("username");
String mobile = rs.getString("mobile");
String cardnumber = rs.getString("cardnumber");
DbUser dbUser = new DbUser();
dbUser.setId(id);
dbUser.setUsername(username);
dbUser.setMobile(mobile);
dbUser.setCardnumber(cardnumber);
return dbUser;
}
}
public DbUser save(DbUser dbUser){
if(dbUser.getId() == null){
int id = insertDbUserAndReturnId(dbUser);
return jdbcTemplate.queryForObject(SQL_FINDBYID_DBUSER, new DbUserRowMapper(), id);
}
jdbcTemplate.update(SQL_UPDATE_DBUSER, dbUser.getUsername(), dbUser.getMobile(), dbUser.getCardnumber(), dbUser.getId());
return dbUser;
}
public int insertDbUserAndReturnId(DbUser dbUser){
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate).withTableName("user_list");
jdbcInsert.setGeneratedKeyName("id");
Map map = new HashMap<>();
map.put("username", dbUser.getUsername());
map.put("mobile", dbUser.getMobile());
map.put("cardnumber", dbUser.getCardnumber());
int id = jdbcInsert.executeAndReturnKey(map).intValue();
return id;
}
}