spring data jdbc的简单教程

你需要先做一番配置,跟我来!

目录

配置springconfig

数据库和实体类配置。

数据库:就俩字段,一个是userid,一个是username

实体类:

DAO层接口:

开始测试:

其他一些事项:

结语:

 

配置springconfig

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

数据库和实体类配置。

数据库:就俩字段,一个是userid,一个是username


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怎么办?没办法。

DAO层接口:

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跟个鸡肋一样

 

你可能感兴趣的:(springdata)