命名查询
spring data jdbc最底层的接口是Repository
@Indexed
public interface Repository<T, ID> {
}
其次是CrudRepository,其继承Repository接口
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
//里面有很多定义好的方法
...
}
然后是PagingAndSortingRepository,其继承CrudRepository
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
//比CrudRepository多了分页和排序的方法
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
第一种使用方法就是自定义Repository接口,继承PagingAndSortingRepository接口,然后可以使用其默认的实现好的方法,只要按照其规定好的方法格式,框架会帮我们生成sql语句,与数据库交互,例如:
@Repository
interface JobRepository extends PagingAndSortingRepository<Job, Long> {
//根据工作id查询工作
List<Job> findByJobId(long jobId);
}
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Table("job")
public class Job {
private long jobId;
private long name;
}
官网提供了一些其他的形象查询方法:
interface PersonRepository extends Repository<Person, Long> { List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // Enables the distinct flag for the query List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enabling ignoring case for an individual property List<Person> findByLastnameIgnoreCase(String lastname); // Enabling ignoring case for all suitable properties List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // Enabling static ORDER BY for a query List<Person> findByLastnameOrderByFirstnameAsc(String lastname); List<Person> findByLastnameOrderByFirstnameDesc(String lastname); }
同时也支持嵌套属性的查询
List<Person> findByAddress_ZipCode(ZipCode zipCode);
同时除了我们传入的实体类的属性,Spring Data Jdbc还识别 Page , Sort 等参数
Page<User> findByLastname(String lastname, Pageable pageable); Slice<User> findByLastname(String lastname, Pageable pageable); List<User> findByLastname(String lastname, Sort sort); List<User> findByLastname(String lastname, Pageable pageable);
Sort sort = Sort.by("firstname").ascending() .and(Sort.by("lastname").descending()); //当然也可以这样,更加地安全 TypedSort<Person> person = Sort.sort(Person.class); Sort sort = person.by(Person::getFirstname).ascending() .and(person.by(Person::getLastname).descending());
Pageable pageable=PageRequest.of(1, 20)
甚至可以限制查询个数
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable); Slice<User> findTop3ByLastname(String lastname, Pageable pageable); List<User> findFirst10ByLastname(String lastname, Sort sort); List<User> findTop10ByLastname(String lastname, Pageable pageable);
返回类型
Streamable
Iterable
Collections
Stream
可以自定义//Streamable和StreamStream的区别在于Stream必须关闭 try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) { stream.forEach(…); } Streamable<Person> result = repository.findByFirstnameContaining("av") .and(repository.findByLastnameContaining("ea"));
空值的指定
import org.springframework.lang.Nullable; interface UserRepository extends Repository<User, Long> { //入参和返回值有一个为空,抛出异常IllegalArgumentException User getByEmailAddress(EmailAddress emailAddress); //入参和返回值均可以是null @Nullable User findByEmailAddress(@Nullable EmailAddress emailAdress); //没有查询到返回Optional.empty(),但是入参为空时抛出异常IllegalArgumentException Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress); }
异步返回结果
@Async Future<User> findByFirstname(String firstname); @Async CompletableFuture<User> findOneByFirstname(String firstname); @Async ListenableFuture<User> findOneByLastname(String lastname);
@Query注解
优先注解查询,没有注解去找命名查询。
interface UserRepository extends CrudRepository<User, Long> {
@Query("select firstName, lastName from User u where u.emailAddress = :email")
User findByEmailAddress(@Param("email") String email);
}
//可以使用 @Modifying on 查询方法将查询标记为修改查询,如以下示例所示
@Modifying
@Query("UPDATE DUMMYENTITY SET name = :name WHERE id = :id")
boolean updateName(@Param("id") Long id, @Param("name") String name);
jdbcTempalte
参考文章(https://www.cnblogs.com/wenxuehai/p/14716372.html)
介绍
JdbcTemplate 是 Spring 对 JDBC 的封装,目的是使JDBC更加易于使用,JdbcTemplate是Spring的一部分。JdbcTemplate 处理了资源的建立和释放,它帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果即可。
Spring为了简化数据库访问,主要做了以下几点工作:
- 提供了简化的访问JDBC的模板类,不必手动释放资源;
- 提供了一个统一的 DAO 类以实现 Data Access Object 模式;
- 把
SQLException
封装为DataAccessException
,这个异常是一个RuntimeException
,并且让我们能区分SQL异常的原因,例如,DuplicateKeyException
表示违反了一个唯一约束;- 能方便地集成Hibernate、JPA和MyBatis这些数据库访问框架。
常用方法
jdbcTemplate主要提供的5类方法及使用:
(1)execute() 方法:可以执行任何SQL语句,一般用于执行DDL语句。
(2)update(sqlStr, 参数列表) 方法:用于执行新增、修改、删除等语句。
(3)batchUpdate() 方法:用于执行批处理相关语句,batchUpdate方法第二参数是一个元素为 Object[] 数组类型的 List 集合。
(4)query() 方法及 queryForXXX() 方法:用于执行查询相关语句,查询结果为基本数据类型或者是单个对象一般使用 queryForObject()
- queryForInt():查询一行数据并返回 int 型结果。例子:jdbcTemplate.queryForInt(“select count(*) from user”)
- queryForObject(sqlStr, 指定的数据类型, 参数列表):查询一行任何类型的数据,最后一个参数指定返回结果类型。例子:jdbcTemplate.queryForObject(“selct count(*) from user”, Integer.class)
- queryForMap(sqlStr, 参数列表):查询一行数据并将该行数据转换为 Map 返回。将会将列名作为key,列值作为 value 封装成 map。当查询出来的行数大于1时会报错。例子:jdbcTemplate.queryForMap(“select * from user where username = ?”, “aaa”);``
- List<Map<String, Object>> queryForList(sqlStr, 参数列表):将查询结果集封装为 list 集合,该集合的每一条元素都是一个 map。
- query(sqlStr, RowMapper对象, 参数列表):查询多行数据,并将结果集封装为元素是 JavaBean 的 list。(注意,指定的JavaBean的属性最好不要是基本类型,因为查询出来的结果可能是null,而null赋值为基本数据类型将会报错。比如int最好定义为Integer)
(5)call() 方法:用于执行存储过程、函数相关语句。
具体方法介绍
增
//单个新增
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addUser(User user) {
//创建SQL语句
String sql = "insert into user values(?, ?, ?)";
//调用方法执行SQL
int updateRow = jdbcTemplate.update(sql, user.getId(), user.getName(), user.getPassword());
System.out.println(updateRow);
}
}
//批量新增
@Repository
public class UserDaoImpl implements UserDao {
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addBath(List<Object[]> userList) {
String sql = "insert into user values(?, ?, ?)";
/*
List<Object[]> userList = new ArrayList<>();
Object[] arr1 = {1, "name1", "password1"};
Object[] arr2 = {2, "name2", "password2"};
Object[] arr3 = {3, "name3", "password3"};
userList.add(arr1);
userList.add(arr2);
userList.add(arr3);
*/
int[] ints = jdbcTemplate.batchUpdate(sql, userList); //batchUpdate方法第二个参数是集合,该集合元素是数组,数组里面的每个值对应着添加到数据库表里面的字段值。该方法返回影响行数数组
System.out.println(Arrays.toString(ints));
}
}
改删
//单个修改 删除
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void updateUser(User user) {
String sql = "update user set name=?, password=? where id=?";
int updateRow = jdbcTemplate.update(sql, user.getName(), user.getPassword(), user.getId());
System.out.println(updateRow);
}
@Override
public void deleteUser(int userId) {
String sql = "delete from user where id=?";
int updateRow = jdbcTemplate.update(sql, userId);
System.out.println(updateRow);
}
}
//批量修改 删除
@Repository
public class UserDaoImpl implements UserDao {
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//批量修改
@Override
public void updateBatch(List<Object[]> listArg) {
String sql = "update user set name=?, password=? where id=?";
/*
List<Object[]> userList = new ArrayList<>();
Object[] arr1 = {1, "name1", "password1"};
Object[] arr2 = {2, "name2", "password2"};
Object[] arr3 = {3, "name3", "password3"};
userList.add(arr1);
userList.add(arr2);
userList.add(arr3);
*/
int[] ints = jdbcTemplate.batchUpdate(sql, listArg);
System.out.println(Arrays.toString(ints));
}
//批量删除
@Override
public void deleteBath(List<Object[]> listArg) {
String sql = "delete from user where id=?";
/*
List<Object[]> userList = new ArrayList<>();
Object[] arr1 = {6};
Object[] arr2 = {7};
userList.add(arr1);
userList.add(arr2);
*/
int[] ints = jdbcTemplate.batchUpdate(sql, listArg);
System.out.println(Arrays.toString(ints));
}
}
查询
queryForObject (sqlStr, 指定的数据类型, 参数列表):查询一行任何类型的数据,最后一个参数指定返回结果类型。
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int getUserCount() {
String sql = "select count(*) from user";
int userCount = jdbcTemplate.queryForObject(sql, int.class); //第二个参数是返回类型的class
return userCount;
}
}
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public User getUserInfo(int userId) {
String sql = "select * from user where id=?";
// rowMapper 是一个接口,可以使用这个接口里面的实现类完成数据的封装,规定每一行记录和JavaBean的属性如何映射
User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), userId);
return user;
}
}
query (sqlStr, RowMapper对象, 参数列表):查询多行数据,并将结果集封装为元素是 JavaBean 的 list。(注意,指定的 JavaBean 的属性最好不要是基本类型,因为查询出来的结果可能是null,而null赋值为基本数据类型将会报错。比如int最好定义为Integer)
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public List<User> getAllUser() {
String sql = "select * from user";
List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
return userList;
}
}