目录
配置springconfig
数据库和实体类配置。
数据库:就俩字段,一个是userid,一个是username
实体类:
DAO层接口:
开始测试:
其他一些事项:
结语:
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.data.jdbc.repository.config.JdbcConfiguration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import com.alibaba.druid.pool.DruidDataSource;
@Configuration
@EnableJdbcRepositories("com.dao")//这里应该会自动enable
public class CustomerConfig extends JdbcConfiguration {
/**
这个也应该会自动装备
*/
@Bean
NamedParameterJdbcOperations operations() {
return new NamedParameterJdbcTemplate(dataSource());
}
@Bean
DataSource dataSource() {
DruidDataSource source = new DruidDataSource();
source.setDriverClassName("com.mysql.cj.jdbc.Driver");
source.setUrl("jdbc:mysql://localhost:3307/te");
source.setUsername("root");
source.setPassword("123");
return source;
}
}
这里设置了NamedParameterJdbcOperations 参数模板,数据库datasouce,以及装配了自动jdbc库EnableJdbcRepositories自动装配且扫包.
什么是参数模板呢?
就mybatis来说:
select * from user where userid = #{userid}
#{}就是入参的模板配置。
那么springdatajdbc不是#{},而是:,就是冒号,例如:
select * from user where userid = :userid
Create Table
CREATE TABLE `user` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8
public class User {
@Id
private Integer userid;
private String username;
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [userid=" + userid + ", username=" + username + "]";
}
}
这里要注意:这个实体类必须要有id属性,id属性必须要加上@id,这个注解是org.springframework.data.annotation.Id;可不是JPA的javax包下的。
如果没有加注解会怎么办?会报错。
如果数据库表本身就没有id怎么办?没办法。
public interface UserDao extends CrudRepository{
}
什么都没有,空空如也。
CrudRepository是什么?CrudRepository继承自Repository,Repository只是一个springdata的标记接口,里面什么都没有。
我们不要继承自Repository,而是继承自CrudRepository,它里面有些基本的crud增删改查的方法,如下:
Optional findById(ID id);
boolean existsById(ID id);
Iterable findAll();
...
...
根据名字可以看出都是一些基本的操作。我们继承了这个,当然也可以获得它的功能。
@ContextConfiguration(classes = CustomerConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class CustomerRepositoryTest {
@Resource
private UserDao dao;
@Test
public void createSimpleCustomer() {
System.out.println("-------");
System.out.println(dao.findById(2));
System.out.println("-----");
}
}
执行之后,是可以运行的.也可以打印出来id为2的user
这就意味着我们不需要写dao层的实现类,spring已经自动为我们去做了一些事情.
1.我们查看下CrudRepository的继承树,发现CrudRepository还有个子类PagingAndSortingRepository
public interface PagingAndSortingRepository extends CrudRepository {
Iterable findAll(Sort sort);
Page findAll(Pageable pageable);
}
这个里面又多了两个方法,分别是可以根据排序查询,或者分页查询,
那么我们自己写的接口不去继承CrudRepository而去继承PagingAndSortingRepository不是更好吗?
是的,继承自PagingAndSortingRepository从表面上看比CrudRepository要好的多,因为多了两个常用方法.
但是实际上这两个方法你虽然拥有,可目前来看这两个方法是不能使用的。如果你使用则会报错,至于为什么会报错,请看第4条事项
2.如果我们需要一些特殊的查询方法该怎么办?按下面来做
public interface UserDao extends CrudRepository{
@Query("select * from user where username = :username")
List findByUsername(@Param("username")String username);
}
我们需要自定义sql语句,在方法上加@Query注解,里面就是sql语句。同时参数模板是冒号
3.如果我们需要一些特殊的增删改怎么办?
public interface UserDao extends CrudRepository{
@Modifying
@Query("update user set username = 'ccc' where userid = :id")
void updateForUser(@Param("id")Integer id);
}
依然需要上面加@Query。但如果仅仅是加了@query还是会报错的,还记得jdbc吗?update事件如果走excuteQuery()方法会报错的,你还需要加上一个代表着修改的注解@Modifying让其走修改方法。
4。SpringDataJPA可以通过方法名推断sql语句,那么SpringDataJDBC可以吗?
答案是不可以。
我们先尝试一下:
public interface UserDao extends CrudRepository{
List findByUsername(@Param("username")String username);
}
如果能推断,那么不写@Query,findByUsername方法是可以执行的。
只是它报错。
它最终报错到了:org.springframework.data.jdbc.repository.support.JdbcRepositoryQuery的130行
private String determineQuery() {
String query = queryMethod.getAnnotatedQuery();
if (StringUtils.isEmpty(query)) {
throw new IllegalStateException(String.format("No query specified on %s", queryMethod.getName()));
}return query;
}
这段代码大概意思是:如果@Query注解的sql语句值是个空的话,那么就报错。
我们本来就没有@Query注解,更别提值了。
OK,原代码就这样,我们没有办法推断,那么就必须添加@Query了。
但我们可以进而发现一些奇妙的事情,这个方法往上追溯则是在这里进行调用的:
org.springframework.data.repository.core.support.RepositoryFactorySupport的600行
private Object doInvoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments();if (hasQueryFor(method)) {
return queries.get(method).execute(arguments);
}return invocation.proceed();
}
往上追溯,是红色行执行然后报错。
那么如果我们不使用我们自己写的方法,而是使用CrudRepository的自带方法呢?会发现走的是绿色行。
关键在于hasQueryFor(method)的这个判断。
解释下这句代码的目的:它会判断是否是CrudRepository自带原生的基本方法,如果是原生方法,那么就走绿色行执行自带的sql语句去。如果不是原生方法,那么就取出@Query的sql语句去执行。
queries是一个容器,里面存储了"除了原生方法之外的其他方法"。
那么很明显的是我们自己自定义的方法必须添加@Query.
还有,CrudRepository的子类PagingAndSortingRepository,它的两个方法也不是原生方法。如果我们继承PagingAndSortingRepository,也没有办法去加@Query,所以到此处,竟然也会报错,真是奇哉怪哉。
springdatajdbc跟个鸡肋一样