首先,我们来看一段原生jdbc的代码
public class JdbcDemo { static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = getConnection(); preparedStatement = connection.prepareStatement("select * from user where id = ?"); preparedStatement.setLong(1, 1L); resultSet = preparedStatement.executeQuery(); User user = null; while (resultSet.next()) { long id = resultSet.getLong("id"); String userName = resultSet.getString("user_name"); String name = resultSet.getString("name"); int age = resultSet.getInt("age"); user = new User(id, userName, name, age); } System.out.println(user); } catch (Exception e) { e.printStackTrace(); } finally { if (resultSet != null) { resultSet.close(); } if (preparedStatement != null) { preparedStatement.close(); } if (connection != null) { connection.close(); } } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true", "root", "root"); }}
我们可以看到,从获取获取Connection到关闭Connection释放资源,都需要用户管理,十分繁琐,而且对象映射,sql都采用硬编码,管理十分不方便
接下来,我们来看一下spring对jdbc的封装
public class SpringJdbcDemo { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-jdbc.xml"); JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class); List query = jdbcTemplate.query("select * from user where id = ?", new User(), 1L); System.out.println(query); }}
spring对jdbc进行了封装,提供了数据源的管理,并提供了一个模板方法对数据库进行操作,但是,此时sql还是和代码耦合在一直,并且,我们无法直接象操作java bean一样对数据库进行操作。
mybatis是一个半自动的orm框架,它完美的解决了我们遇到的各种问题,他提供了数据源管理,sql管理,java bean和sql的相互映射,事务,缓存等各个方面的功能。接下来,我们来从一个例子了解mybatis的使用以及相关的配置
public interface UserDao { User get(User user);}
@Data@ToString@NoArgsConstructor@AllArgsConstructorpublic class User { private Long id; private String userName; private String name; private Integer age; public User(Long id) { this.id = id; }}
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
public class MybatisDemo { public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = new User(1L); user = userDao.get(user); System.out.println(user); }}
通过这个简单的实例代码,我们可以看到,在使用spring的时候,我们只需要配置先用的数据源,mapper资源类(其他配置都有其默认值),并为mapper文件创建一个对应的接口,我们就可以直接从SqlSession中获取这个接口对象,然后像操作java bean样去操作数据库
对于返回的java bean,一般,我们需要指定类的全名,针对这种情况,我们可以给这个类配置一个别名,然后在设置返回类型的时候就可以直接使用这个别名
在mybatis中,是如何做到将java bean 映射成sql,有时如何将sql映射成java bean 的呢,其实,这个里面用的就是typeHandler,之所有我们基本没有配置过typeHandler,是因为在mybatis中内置的许多默认的typeHandler,它可以将我们常用的数据类型直接进行映射
public class MyTypeHandler extends BaseTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { String json = JSON.toJSONString(parameter); ps.setString(i, json); } @Override public Object getNullableResult(ResultSet rs, String columnName) throws SQLException { String json = rs.getString(columnName); if (json != null) { return JSON.parseObject(json); } return null; } @Override public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String json = rs.getString(columnIndex); if (json != null) { return JSON.parseObject(json); } return null; } @Override public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String json = cs.getString(columnIndex); if (json != null) { return JSON.parseObject(json); } return null; }}
在mybatis中,提供了一种插件机制,他能够让我们在不更改源码的情况下,扩展mybatis的功能,更改mybatis的核心功能,通过mybatis的插件,我们可以实现像打印日志,分页等功能
@Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); public Object intercept(Invocation invocation) throws Throwable { MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; Object args = invocation.getArgs()[0]; BoundSql boundSql = ms.getBoundSql(args); String sql = boundSql.getSql(); System.out.println(sql); Object returnObject = invocation.proceed(); return returnObject; } public void setProperties(Properties properties) { this.properties = properties; }}
留言与评论(共有 0 条评论) “” |