Spring中JDBCTemplate的入门
Spring是IOC和AOP的容器框架,一站式的框架
连接数据库的步骤:[必须会写]
Spring当中如何配置连接数据库?
第一步配置核心配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 启动Spring注解 --> <context:annotation-config/> <!-- 扫描,如果有多个使用逗号分隔 --> <context:component-scan base-package="com.shxt"/> <!-- 加载属性文件,classpath和classpath*的区别 --> <context:property-placeholder location="classpath:/jdbc.properties"/> <!-- 配置数据源信息 --> <bean id="shxtDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username"> <value>${jdbc.username}</value> </property> <property name="password" value="${jdbc.password}"/> </bean> <!-- 配置完成 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="shxtDataSource"/> </bean> </beans>
package com.shxt.test; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; public class JDBCTest { private ApplicationContext ac =null; private JdbcTemplate jdbcTemplate = null; @Before public void init(){ //读取核心配置文件 ac = new ClassPathXmlApplicationContext("beans.xml"); //获取JdbcTemplate对象,通过id的方式, JdbcTemplate.class就是强转 jdbcTemplate = ac.getBean("jdbcTemplate",JdbcTemplate.class);//强转 } @Test public void 添加角色的操作_第一种方式(){ String sql = "insert into sys_role(role_name,role_desc) values ('悟空','齐天大圣')"; //不正规 //默认情况下JDBC的事务是自动提交的,而大部分的持久层框架是需要手动提交的 int rownum = jdbcTemplate.update(sql);//delete/update/insert的sql语句 System.out.println(rownum); } }
代码优化
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 启动Spring注解 --> <context:annotation-config/> <!-- 扫描,如果有多个使用逗号分隔 --> <context:component-scan base-package="com.shxt"/> <!-- 加载属性文件,classpath和classpath*的区别 --> <context:property-placeholder location="classpath:/jdbc.properties"/> <!-- 配置数据源信息 --> <bean id="shxtDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${jdbc.driver}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="shxtDataSource" /> </beans>
代码说明: <bean id="shxtDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName[对应的是set方法]="${jdbc.driver}" p:url[对应的是set方法]="${jdbc.url}" p:username[对应的是set方法]="${jdbc.username}" p:password[对应的是set方法]="${jdbc.password}" /> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource[对应的是set方法]-ref[引用]="shxtDataSource" />
@Test public void 添加角色的操作_第二种方式_推荐方式_预处理方式(){ String sql = "insert into sys_role(role_name,role_desc) values (?,?)"; //int rownum = jdbcTemplate.update(sql, new Object[]{"八戒","天蓬元帅"}); int rownum = jdbcTemplate.update(sql, "八戒","天蓬元帅"); System.out.println(rownum); }
如果使用Hibernate或者Mybatis类似的持久层框架,他们都可以通过配置返回你添加数据的主键
Mybatis是如何配置?请补充代码,映射文件内容
有待补充
---->>>> 如果涉及到Oracle数据库,建议使用官方写法,因为Oracle没有自增长的字段,是通过序列完成自增长操作
final String INSERT_SQL = "insert into my_test (name) values(?)"; // 老版本因为是内部类,所有需要使用final final String name = "Rob"; KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update( new PreparedStatementCreator() { public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] {"id"});//id为主键字段 ps.setString(1, name);//PreparedStatement 1代表第一个问好 return ps; } }, keyHolder); // keyHolder.getKey() now contains the generated key
@Test public void 添加角色的操作_关于主键_前提必须使用自增长的方式(){ String sql = "insert into sys_role(role_name,role_desc) values (?,?)"; Role role = new Role(); role.setRole_name("唐僧"); role.setRole_desc("金蝉子"); KeyHolder keyHolder = new GeneratedKeyHolder();//使用Ctrl+T的方式,看KeyHolder的实现类 jdbcTemplate.update(new PreparedStatementCreator() { @Override //一期内容 public PreparedStatement createPreparedStatement(Connection con) throws SQLException { //1.获取预处理对象 PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); ps.setString(1, role.getRole_name());//注意 1代表的是第一个问号 ps.setString(2, role.getRole_desc());//注意 2代表的是第二个问号 return ps; } }, keyHolder); int pk = keyHolder.getKey().intValue();//getKey()返回为Number类型 role.setRole_id(pk); System.out.println(role.getRole_id()); }
关于更新操作和删除操作类似,如果涉及到批量添加和更新问题,请自行扩展学习
测试查询操作:
@Test public void 通过查询返回单一的值(){ String sql = "select count(*) from sys_role where role_name like ?"; Integer count = jdbcTemplate.queryForObject(sql, Integer.class, "%1%");//Integer.class 强转 //Integer count = jdbcTemplate.queryForObject(sql, new Object[]{"%员%"}, Integer.class); System.out.println(count); }
返回一条数据的形式:
@Test public void 返回一条数据_Map形式(){ String sql = "select * from sys_role where role_id=?"; Map<String,Object> map = jdbcTemplate.queryForMap(sql, 405); System.out.println(map); }
@Test public void 返回一条数据_对象形式(){ String sql = "select * from sys_role where role_id=?";//一期关系 Role role = jdbcTemplate.queryForObject(sql, new Object[]{405},new RowMapper<Role>(){ @Override //Java的内部类?匿名类? public Role mapRow(ResultSet rs, int rowNum) throws SQLException { Role role = new Role(); role.setRole_id(rs.getInt("role_id")); role.setRole_name(rs.getString("role_name")); role.setRole_desc(rs.getString("role_desc")); role.setRole_photo(rs.getString("role_photo")); role.setRole_status(rs.getString("role_status")); return role; } }); System.out.println(role); }
返回列表数据
@Test public void 返回列表数据_List_Map形式(){ String sql = "select * from sys_role where role_name like ?"; List<Map<String,Object>> dataList = jdbcTemplate.queryForList(sql, "%1%"); System.out.println(dataList); }
@Test public void 返回列表数据_List_对象形式(){ String sql = "select * from sys_role where role_name like ?"; List<Role> roleList = jdbcTemplate.query(sql, new Object[]{"%员%"}, new RowMapper<Role>(){ @Override public Role mapRow(ResultSet rs, int rowNum) throws SQLException { Role role = new Role(); role.setRole_id(rs.getInt("role_id")); role.setRole_name(rs.getString("role_name")); role.setRole_desc(rs.getString("role_desc")); role.setRole_photo(rs.getString("role_photo")); role.setRole_status(rs.getString("role_status")); return role; } }); System.out.println(roleList); }
我们发现 返回列表数据_List_对象形式()和返回一条数据_对象形式() 中的代码有重复性质!
public class RoleRowMapper implements RowMapper<Role> { @Override public Role mapRow(ResultSet rs, int rowNum) throws SQLException { Role role = new Role(); role.setRole_id(rs.getInt("role_id")); role.setRole_name(rs.getString("role_name")); role.setRole_desc(rs.getString("role_desc")); role.setRole_photo(rs.getString("role_photo")); role.setRole_status(rs.getString("role_status")); return role; } }
@Test public void 返回一条数据_对象形式_优化(){ String sql = "select * from sys_role where role_id=?";//一期关系 Role role = jdbcTemplate.queryForObject(sql, new Object[]{405},new RoleRowMapper()); //实现类 System.out.println(role); }
@Test public void 返回列表数据_List_对象形式_优化(){ String sql = "select * from sys_role where role_name like ?"; List<Role> roleList = jdbcTemplate.query(sql, new Object[]{"%员%"}, new RoleRowMapper()); //实现类 System.out.println(roleList); }
个人推荐: 超精简版[自己命名的,私人珍藏],通过领域模型自动完成映射
@Test //你需要保持数据库的字段名和属性名保持一致,[没有说完全一致] public void 返回一条数据_对象形式_超精简版(){ String sql = "select * from sys_role where role_id=?";//一期关系 Role role = jdbcTemplate.queryForObject(sql, new Object[]{405},new BeanPropertyRowMapper<Role>(Role.class)); System.out.println(role); } @Test public void 返回列表数据_List_对象形式_超精简版(){ String sql = "select * from sys_role where role_name like ?"; List<Role> roleList = jdbcTemplate.query(sql, new Object[]{"%员%"}, new BeanPropertyRowMapper<Role>(Role.class)); System.out.println(roleList); } @Test public void 返回列表数据_List_对象形式_超精简版_一致的解释(){ String sql = "select role_name , role_desc role_photo1 from sys_role"; List<Role> roleList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Role>(Role.class)); System.out.println(roleList); }
模拟权限分配操作
@Test public void 权限分配() throws Exception{ //1.客户端复选框传递过来一个数组 1,2 菜单的ID Integer[] menus = new Integer[]{1,2}; //2.声明数组 String[] sqls = new String[menus.length+1];//0,1,2 //3.通过ROle_Id 200 删除中间表的信息 sqls[0] = "delete from role_link_menu where fk_role_id=200";//0 //3.新数据添加到中间表 for (int i=0;i<menus.length;i++) { //1,2 sqls[i+1] = "insert into role_link_menu (id,fk_role_id,fk_menu_id) values ('"+UUID.randomUUID().toString()+"',200,"+menus[i]+")"; } jdbcTemplate.batchUpdate(sqls); //MyBatis的实现方式 }
-----------------------------------------
********等价操作*********
-----------------------------------------
通过MyBatis的实现方式,自学内容,MySQL下的操作,设置如下!
&allowMultiQueries=true 新增内容如下:
shxt.driver=com.mysql.jdbc.Driver shxt.url=jdbc:mysql://127.0.0.1:3308/xy37_rbac??useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true shxt.username=root shxt.password=shxt
接口中定义方法,如下推荐使用Map public void permission(Map<String,Object> map);
映射文件代码如下: <delete id="permission" parameterType="map" statementType="PREPARED"> DELETE FROM role_link_menu WHERE fk_role_id=#{role_id}; <foreach collection="menus" item="menu_id" > INSERT INTO role_link_menu (id, fk_role_id, fk_menu_id) VALUES ((SELECT UUID()),#{role_id},#{menu_id}); </foreach> </delete>
测试代码: @Test public void 多条SQL语句执行(){ SqlSession sqlSession = null; try { sqlSession = MyBatisUtils.getSqlSession(); Map<String, Object> map = new HashMap<String,Object>(); map.put("role_id", 200); map.put("menus", new Object[]{1,2,3,6}); sqlSession.getMapper(UserMapper.class).permission(map); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); }finally { MyBatisUtils.closeSqlSession(sqlSession); } }