当前位置: 首页 > article >正文

SpringBoot的数据访问

Docker

CentOS安装命令

sudo yum update
sudo yum install docker

Ubuntu安装命令

sudo apt-get update
sudo apt-get docker.io

Windows下安装

windows运行Docker是通过Boot2Docker(https://github.com/boot2docker/windows-installer/releases/latest)实现的
这个软件包含一个VirtualBox,只适合开发测试,不适合生产环境

安装前确认电脑的BIOS设置中的CPU虚拟化技术支持已经开启

Docker的镜像都是放在Docker官网https://registry.hub.docker.com

docker search redis  # 检索redis

docker pull redis # 下载redis镜像

docker images #查看本地镜像列表

docker rmi image-id #删除指定镜像

docker rmi ${docker images -q} #删除所有镜像


docker run --name test-redis -d redis #运行一个Redis容器

docker ps #查看运行中的容器列表

docker ps -a #查看运行和停止状态的容器

docker stop test-redis #停止redis容器

docker start test-redis #启动redis容器

docker rm container-id #删除指定id的容器

docker rm $(docker ps -a -q) #删除所有容器

docker logs container-name/container-id #查看当前容器日志
#例如查看redis容器的日志
docker logs port-redis
# 映射容器的6379端口到本机的6378端口
docker run -d -p 6378:6379 --name port-redis redis

docker exec -it container-id/container-name bash #登录并访问当前容器,通过exit命令退出登录

# 将容器的Oracle XE管理界面的8080端口映射为本机的9090端口,将Oracle XE的1521端口映射为 本机的1521端口
docker run -d -p 9090:8080 -p 1521:1521 wnameless/oracle-xe-llg

容器:
hostname:localhost
端口:1521
SID:XE
username:system/sys
password:oracle

管理界面:
url: http://localhost:9090/apes
workspace:internal
username:admin
password:oracle

Spring Data JPA

属于Spring Data的一个子项目,通过提供基于JPA的Repository减少了JPA作为数据访问方案的代码量

①、继承JpaRepository意味着默认有了数据访问的操作方法

public interface PersonRepository extends JpaRepository<Person,Long>{
	//定义数据访问操作的方法
}

②、配置使用Spring Data JPA

@Configuration
@EnableJpaRepositories("com.wisely.repos")//开启JPA,并扫描包下接口
public class JpaConfiguration{
	
	@Bean
	public EntityManagerFactory entityManagerFactory(){

	}
}

③、定义查询方法

表——实体类

Ⅰ、根据属性名查询

public interface PersonRepository extends JpaRepository<Person,Long>{
	
	//select p from Person p where p.name=?1
	List<Person> findByName(String name);

	//select p from Person p where p.name like ?1
	List<Person> findByNameLike(String name);

	//select p from Person p where p.name=?1 and p.address=?2
	List<Person> findByNameAndAddress(String name,String address);

	//获得符合查询条件的钱10条数据
	List<Person> findFirst10ByName(String name);
	
	//获得符合查询条件的前30条数据
	List<Person> findTop30ByName(String name);
}

Ⅱ、使用JPA的NamedQuery查询

即一个名称映射一个查询语句

@Entity
@NamedQuery(name="Person.findByName",query="select p from Person p where p.name=?1")
public class Person{

}
public interface PersonRepository extends JpaRepository<>{
	
	//使用NamedQuery里定义的查询语句,而不是根据方法名查询
	List<Person> findByName(String name);
}

Ⅲ、使用@Query查询


public interface PersonRepository extends JpaRepository<Person,Long>{
	
	//使用参数索引查询
	@Query("select p from Peron p where p.address=?1")
	List<Person> findByAddress(String address);
	
	//使用命名参数
	@Query("select p from Person p where p.address=:address")
	List<Person> findByAddress(@Param("address") String address);
	
	//@Modifying和@Query组合注解来更新查询,返回值表示影响的行数
	@Modifying
	@Transactional
	@Query("update Person p set p.name=?1")
	int setName(String name);
}

Ⅳ、Specification规范接口构造条件查询

//接口必须实现JpaSpecificationExecutor
public interface PersonRepository extends JpaRepository<Person,Long>,JpaSpecificationExecutor<Person>{
	
}
//定义Criterial查询
public class CustomerSpecs{
	
	public static Specification<Person> personFromHefei(){
		//使用Root获取需要查询的属性,查询所有来自合肥的人
		@Override
		public Predicate toPredicate(Root<Person> root,CriteriaQuery<?> query,CriteriaBuilder cb){
			return cb.equal(root.get("address"),"合肥");
		}
	}
}
List<Person> people = personRespository.findAll(personFromHefei());

Ⅴ、排序与分页

//定义
public interface PersonRepository extends JpaRepository<Person,Long>{
	
	List<Person> findByName(String name,Sort sort);
	Page<Person> findByName(String name,Pageable pageable);
}
//使用排序
List<Person> people = personRepository.findByName("xx",new Sort(Direction.ASC,"age"));
Sort(Direction.ASC,"age")
//使用分页(获得当前页面的记录、总页数、总记录数、是否有上一页或下一页)
Page<Person> people2 = personRespository.findByName("xx",new PageRequest(0,10));

一、新建项目

依赖:spring-boot-starter-data-jpa spring-boot-starter-web ojdbc6 guava(包含Java常用工具类)

Maven中心库没有OracleJDBC驱动,需要通过Maven进行打包到本地仓库
Oracle官网下载ojdbc6.jar 通过控制台命令mvn install:install-file -DgroupId=com.oracle “-DartifactId=ojdbc6” -Dversion=11.2.0.2.0" “-Dpackaging=jar” “-Dfile=E:\odjbc6.jar”

  • -DgroupId=com.oracle 指定当钱包的groupId为com.oracle
  • -DartifactId=odjbc6 指定当前包的artifactfactId为ojdbc6
  • -Dversion=11.2.0.2.0 指定当钱包version为11.2.0.2.0
  • -Dfile=E:\odjbc6.jar 指定要打包的jar文件位置

新建一个data.sql放置在src/main/resources下,内容向表中增加一些数据

二、配置基本属性

appliation.properties里配置数据源和jpa的相关属性

spring.datasource.driverClassName=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc\:oracle\:thin\:@localhost\:1521\:xe
spring.datasource.username=boot
spring.datasource.password=boot

#hibernate提供根据实体类自动维护数据表结构的功能(create create-drop update validate none)
spring.jpa.hibernate.ddl-auto=update
#控制台现实sql
spring.jpa.show-sql=true
#控制器输出json字符串格式
spring.jackson.serialization.indent_output=true

三、定义实体类映射

@Entity //指明实体类
@NamedQuery(name="Person.withNameAndAddressNamedQuery",query="select p from Person p where p.name=?1 and address=?2")
public class Person {
	
	@Id//指明这个属性映射为数据库的主键
	@GeneratedValue//默认主键生成方式为自增,hibernate会自动生成一个名为HIBERNATE_SEQUENCE的序列
	private Long id;

	private String name;

	private Integer age;

	private String address;

	//省略无参、有参构造和get/set方法	
}

四、数据访问接口

public interface PersonRepository extends JpaRepository<Person,Long>{
	
	List<Person> findByAddress(String name);//使用方法名查询

	Person findByNameAndAddress(String name,String address);

	//使用@Query查询
	@Query("select p from Person p where p.name=:name and p.address=:address")
	Person withNameAndAddressQuery(@Param("name")String name,@Param("address")String address);
	
	//使用@NamedQuery查询,实体类中做@NamedQuery定义
	List<Person> withNameAndAddressNameQuery(String name,String address);
}

五、控制器

@RestController
public class DataController{
	
	//spring data JPA自动注册bean
	@Autowired
	PersonRepository personRepository;

	@RequestMapping("/save")
	public Person save(String name,String address,Integer age){
		Person p = personRepository.save(new Person(null,name,age,address));
		return p;
	}

	@RequestMapping("/q1")
	public List<Person> q1(String address){
		List<Person> people = personRepository.findByAddress(address);
		return people;
	}

	@RequestMapping("/q2")
	public Person q2(String name,String address){
		Person people = personRepository.findByNameAndAddress(name,address);
		return people;
	}
	
	@RequestMapping("/q3")
	public Person q3(String name,String address){
		Person p =personRepository.withNameAndAddressQuery(name,address);
		return p;
	}

	@RequestMapping("/q4")
	public Person q4(String name,String address){
		Person p = personRepository.withNameAndAddressNamedQuery(name,address);
		return p;
	}

	@RequestMapping("/sort")
	public List<Person> sort(){
		List<Person> people = personRepository.findAll(new Sort(Direction.ASC,"age"));
		return people;
	}

	@RequestMapping("/page")
	public Page<Person> page(){
		Page<Person> pagePeople = personRepository.findAll(new PageReqeust(1,2));
		return pagePeople;
	}
}

六、自定义Repository实现自动模糊查询

①、定义Specification

public class CustomerSpecs{
	
	public static <T> Specification<T> byAuto(final EntityManager entityManager,final T example){//
		
		final Class<T> type = (Class<T>) example.getClass();//

		return new Specification<T>(){
			@Override
			public Predicate toPredicate(Root<T> root,CriteriaQuery<?> query,CriteriaBuilder cb){
				List<Predicate> predicates = new ArrayList<>();//
				EntityType<T> entity = entityManager.getMetaModel().entity(type);//
				
				for(Attribute<T,?> attr:entity.getDeclaredAttributes()){//
					Object attrValue = getValue(example,attr);//
					if(attrValue != null){
						if(attr.getJavaType() == String.class){//
							if(!StringUtils.isEmpty(attrValue)){//
								predicates.add(cb.like(root.get(attriute(entity,attr.getName(),String.class)),
												pattern((String)strValue)));//
							}
						}else{
							predicates.add(cb.equal(root.get(attribute(entity,attr.getName(),attrValue.getClass())),attrValue));
						}
					}
				}
				return predicates.isEmpty()?cb.conjunction():cb.and(toArray(predicates,Predicate.class));//
			}

			private <T> Object getValue(T example,Attribute<T,?> attr){
				return ReflectionUtils.getField((Field) attr.getJavaMember(),example);
			}

			//
			private<E,T> SingularAttribute<T,E> attribute(EntityType<T> entity,String filedName,Class<E> fieldClass){
				return entity.getDeclaredSingularAttribute(filedName,fieldClass);
			}
		};
	}

	//
	static private String pattern(String str){
		return "%" + str + "%";
	}
}

②、定义接口

@NoRepositoryBean
public interface CustomRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T>{
	Page<T> findByAuto(T example,Pageable pageable);
}

③、定义实现

public class CustomRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID>
	implements CustomRepository<T,ID>{
	
	private final EntityManager entityManager;
	public CustomRepositoryImpl(Class<T> domainClass,EntityManager entityManager){
		super(domainClass,entityManager);
		this.entityManager = entityManager;
	}

	@Override
	public Page<T> findByAuto(T example,Pageable pageable){//构造查询条件,提供分页功能
		return finalAll(byAuto(entityManager,example),pageable);
	}
}

④、repositoryFactoryBean

public class CustomRepositoryFactoryBean<T extends JpaRepository<S,I>,S,ID extends Serializable>
	extends JpaRepositoryFactoryBean<T,S,ID>{
	
	@Override
	protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager){
		return new CustomRepositoryFactory(entityManager);
	}

	private static class CustomRepositoryFactory extends JpaRepositoryFactory{
		public CustomRepositoryFactory(EntityManager entityManager){
			super(entityManager);
		}

		@Override
		@SupprssWarnings({"unchecked"})
		protected <T,ID extends Serializable> SimpleJpaRepository<?,?> getTargetRepository(RepositoryInformation information,
					EntityManager entityManager){
			return new CustomRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
		}

		@Override
		protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){
			return CustomRepositoryImpl.class;
		}
	}
}

⑤、使用

只需要让实体类Repository继承自定义的Repository接口,即可使用自定义Repository中实现的功能

public interface PersonRepository extends CustomRepository<Person,Long>{

	List<Person> findByAddress(String address);
	Person findByNameAndAddress(String name,String address);

	@Query("select p from Person p where p.name=:name and p.address=:address")
	Person withNameAndAddressQuery(@Param("name") String name,@Param("address") String address);
	
	Person withNameAndAddressNamedQuery(String name,String address);
}

在实体类定义的数据类型要用包装类型(Long,Integer),而不能使用原始数据类型(long ,int)
因为在SpringMVC中使用原始数据类型会自动初始化为0,而不是空,导致构造条件失败

@RestController
public class DataController{
	
	@RequestMapping("/auto")
	public Page<Person> auto(Person person);

	Page<Person> pagePeople = personRepository.findByAuto(person,new PageRequest(0,10));
	return pagePeople;
}

⑥、配置

如果不需要自定义Repository实现,则在Spring Data JPA里无须添加@EnableJpaRepositories注解
因为@SpringBootApplication饱含了@EnableAutoConfiguration注解开启了对Spring Data JPA的支持

@SpringBootApplicaiton
//自定义的Repository实现起效
@EnableJpaRepositories(repositoryFactoryBeanClass=CustomRepositoryFactoryBean.class)
public class Ch82Application{
	
	@Autowired
	PersonRepository personRepository;

	public static void main(String[] args){
		SpringApplication.run(Ch82Application.class,args);
	}
}

运行http://localhost:8080/auto无构造查询全部
http://localhost:8080/auto?address=肥,构造address的like查询

Spring Data REST

①、依赖

spring-boot-starter-data-jpa spring-boot-starter-data-rest

②、application.properties中配置属性

spring.data.rest.base-path:java.net.URI
spring.data.rest.default-page-size:int
spring.data.rest.limit-param-name:String
sprig.data.rest.max-page-size:int
spring.data.rest.page-param-name:String
spring.data.rest.return-body-on-create:boolean
spring.data.rest.return-body-on-update:boolean

③、实体类

@Entity
public class Person{
	@Id
	@GeneratedValue
	private Long id;

	private String name;

	private Integer age;

	private String address;

	//有参构造,无参构造,get/set方法省略
}

④、实体类的Repository

public interface PersonRepository extends JpaRepository<Person,Long>{
	
	Person findByNameStartsWith(String name);
}

⑤、安装Chrome插件Postman REST Client

Postman是一个支持REST的客户端,测试REST资源

声明式事务

①、依赖

spring-boot-starter-data-jpa spring-boot-starter-web

②、配置相关属性(略)

③、实体类(Person略)

④、实体类Repository

public interface PersonRepository extends JpaRepository<Person,Long>{

}

⑤、Service业务

public interface DemoService{
	public Person savePersonWithRollBack(Person person);
	public Person savePersonWithoutRollBack(Person person);
}
@Service
public class DemoServiceImpl implements DemoService{
	
	@Autowired
	PersonRepository personRepository;

	//指定特定的异常,数据回滚,数据库不会新增
	@Transactional(rollbackFor={IllegalArgumentException.class})
	public Person savePersonWithRollBack(Person person){
		
		Person p = personRepository.save(person);
		
		if(person.getName().equals("jordan")){
			//硬编码手动出发异常
			throw new IllegalArgumentException("Jordan,已存在,数据将回滚");
		}
		return p;
	}

	//虽然抛出异常,但数据并没有回滚
	@Trancational(noRollbackFor={IllegalArgumentException.class})
	public Person savePersonWithoutRollBack(Person person){
		
		Person p = personRepository.save(person);

		if(person.getName().equals("jordan")){
			throw new IllegalArgumentException("Jordan,已存在,数据不会回滚");
		}
		return p;
	}
	
}

数据缓存

Spring提供四个注解声明缓存规则

  • @Cacheable 方法执行前先判断缓存中是否有数据,如果有直接返回缓存,如果没有调用方法的返回值放进缓存
  • @CachePut 无论怎样,都会将方法的返回值放进缓存
  • @CacheEvict 将一条或多条数据从缓存中删除
  • @Caching 可以通过@Caching注解组合多个注解策略在一个方法上

其中@Cacheable/@CachePut/@CacheEvit都有value属性
指定的是要使用缓存名称,key属性指定的是数据在缓存中的存储的键

①、依赖

spring-boot-starter-cache
spring-boot-starter-data-jpa
spring-boot-starter-web

②、实体类Person略

③、实体类Repository

public interface PersonRepository extends JpaRepository<Person,Long>{

}

④、业务接口以及实现类

public interface DemoService{
	
	public Person save(Person person);
	public void remove(Long id);
	public Person findOne(Person person); 
}
@Service
public class DemoServiceImpl implements DemoService{
	
	@Autowired
	PersonRepository personRepository;

	@Override
	@CachePut(value="people",key="#person.id")//缓存新增或更新,缓存名称为people,数据key是person的id
	public Person save(Person person){
		Person p = personRepository.save(person);
		System.out.println("为id、key为:"+p.getId()+"数据做了缓存");
		return p;
	}

	@Override
	@CacheEvict(value="people")//从缓存中删除key为id的数据
	public void remove(Long id){
		System.out.println("删除了id、key为"+id+"的数据缓存");
		personRepository.delete(id);
	}

	@Override
	@Cacheable(value="people",key="#person.id")//缓存key为person的id数据到缓存people
	public Person findOne(Person person){
		Person p = personRepository.findOne(person.getId());
		System.out.println("为id、key为:"+p.getId()+"数据做了缓存");
		return p;
	}
}

⑤、开启缓存支持

@SpringBootApplication
@EnableCaching //开启缓存支持
public class ChApplication{
	//略
}

第一次调用方法查询数据库会有sql语句在控制台
第二次没有sql,直接从缓存中拿数据

切换缓存技术

使用EhCache作为缓存技术

①、依赖

ehcache

EhCache需要的配置文件ehcache.xml放在 类路径下,SpringBoot自动扫描
SpringBoot会自动配置EhCacheCacheManager的Bean

<ehcache>
	<cache name="people" maxElementsInMemory="1000"></ehcache>
</ehcache>

使用Guava作为缓存技术

①、依赖

guava

SpringBoot会自动配置GuavaCacheManager这个Bean

使用Redis作为缓存技术

①、依赖

spring-boot-starter-redis

SpringBoot自动配置RedisCacheManager以及RedisTemplate的Bean

非关系型数据库NoSQL

不适用SQL语言作为查询语言,数据存储也不是固定的表、字段
主要有文档存储型(MongoDB)、图形关系存储型(Neo4j)和键值对存储型(Redis)

MongoDB

①、安装MongoDB(其数据库管理软件Robomongo)

docker run -d -p 27017:27017 mongo

引入依赖spring-boot-starter-data-mongodb

②、配置信息

spring.data.mongodb.host=#
spring.data.mongodb.port=27017
spring.data.mongodb.uri=mongodb://localhost/test
spring.data.mongodb.database=
spring.data.mongodb.authentication-database=
spring.data.mongodb.grid-fs-database=
spring.data.mongodb.username=
spring.data.mongodb.password=
spring.data.mongodb.repositories.enabled=true #repository是否支持开启,默认为开启
spring.data.mongodb.field-naming-strategy=
org.springfraework.boot.autoconfigure.data.mongo

③、实体类

@Document //注解映射模型和MongoDB的文档
public class Person{
	
	@Id //文档ID
	private String id;
	private String name;
	private Integer age;
	@Field("locs") //此属性在文档中的名称locs
	private Colleciton<Location> locations = new LinkedHashSet<>();

	//省略构造方法和get/set方法
}
public class Location{
	
	private String place;
	
	private String year;

	//省略构造方法和get/set方法
}

④、数据访问

public interface PersonRepository extends MongoRepository<Person,String>{

	Person findByName(String name);//支持方法名查询

	@Query("{'age':?0}")//查询擦书构造JSON字符串即可
	List<Person> withQueryFindByAge(Integer age);
}

⑤、Controller控制器

@RestController
public class DataController{
	
	@Autowired
	PersonRepository personRepository;

	@RequestMapping("/save")
	public Person save(){
		Person p = new Person("wyf",32);
		Collection<Location> locations = new LinkedHashSet<>();
		Location loc1 = new Location("上海","2009");
		Location loc2 = new Location("合肥","2010");
		Location loc3 = new Location("广州","2011");
		Location loc4 = new Location("马鞍山","2012");
		locations.add(loc1);
		locations.add(loc2);
		locations.add(loc3);
		locations.add(loc4);
		p.setLocations(locations);
		return personRepository.save(p);
		
	}

	@RequestMapping("/q1") //
	public Person q1(String name){
		return personReository.findByName(name);
	}

	@RequetMapping("/q2") //
	public List<Person> q2(Integer age){
		return personRepository.withQueryFindByAge(age);
	}
}

Redis

根据Redis不同的Java客户端,Spring Data Redis提供了如下ConnecitonFactory

  • JedisConnectionFactory 使用Jedis作为Redis客户端
  • JredisConnectionFactory 使用Jredis作为Redis客户端
  • LettuceConnectionFactory 使用Lettuce作为Redis客户端
  • SrpConnectionFactory 使用Spullara/redis-protocol作为Redis客户端

①、安装Redis(使用Redis Client管理数据)

docker run -d -p 6379:6379 redis:2.8.21

依赖spring-boot-starter-redis spring-boot-starter-web

②、配置

spring.redis.database=0
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379
spring.redis.pool.max-idle=8 #连接池设置
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.sentinel.master=
spring.redis.sentinel.nodes=
spring.redis.timeout=

③、模型bean

此类必须用时间序列化接口,因为使用Jaskson做序列化需要一个空构造

public class Person implements Serializable{
	
	private static final long serialVersionUID = 1L;

	private String id;
	private String name;
	private Integer age;

	//构造函数,set/get方法
}

④、数据访问

@Repository
public class PersonDao{
	
	@Autowired
	StringRedisTemplate stringRedisTemplate;//SpringBoot已经配置了StringRedisTemplate,可以直接注入

	@Resource(name="stringRedisTemplate")//注入基于字符串的简单属性操作
	ValueOperations<String,String> valOpsStr;

	@Autowired
	RedisTemplate<Object,Object> redisTemplate;//SpringBoot已经配置了RedisTempalte

	@Resource(name="redisTemplate")
	ValueOperations<Object,Object> valOps;//

	public void stringRedisTemplateDemo(){//存储字符串类型
		valOpsStr.set("xx","yy");
	}

	public void save(Person person){
		valOps.set(person.getId(),person);//存储对象类型
	}

	public String getString(){
		return valOpsStr.get("xx");//获得字符串
	}

	public Person getPerson(){
		return (Person) valOps.get("1");//获得对象
	}
}

⑤、配置

SpringBoot自动配置了RedisTemplate,而RedisTemplate使用的是JdkSerializationRedisSerializer(二进制形式存储数据)

这里自定义配置RedisTemplate并定义Serializer

@SpringBootApplication
public class ChApplication{
	
	public static void main(String[] args){
		SpringApplication.run(ChApplication.class,args);
	}

	@Bean
	@SuppressWarnings({"rawtypes","unchecked"})
	public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
												throws UnknownHostException{
		RedisTemplate<Object,Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);

		Jaskson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jaskson2JsonRedisSerializer(Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(Propertyccessor.ALL,JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);

		//设置值value的序列化采用Jackson2JsonRedisSerializer
		template.setValueSerializer(jackson2JsonRedisSerializer);//
		//设置键key的序列化采用StringRedisSerializer
		template.setKeySerializer(new StringRedisSerializer());

		template.aftrPropertiesSet();
		return template;
	}
}

⑥、控制器

@RestController
public class DataController{
	
	@Autowired
	PersonDao personDao;

	@RequestMapping("/set")//设置字符及对象
	public void set(){
		Person person = new Person("1","wyf",32);
		personDao.save(person);
		personDao.stringRedisTemplateDemo();
	}

	@RequestMapping("/getStr")//获得字符
	public String getStr(){
		return personDao.getString();
	}

	@RequestMapping("/getPerson")//获得对象
	public Person getPerson(){
		return personDao.getPerson();
	}
}

http://www.kler.cn/news/332748.html

相关文章:

  • TCP Analysis Flags 之 TCP ZeroWindowProbe
  • 忘记 MySQL 密码怎么办:破解 root 账户密码
  • 【JavaEE】http/https 超级详解
  • 认知杂谈97《兼听则明,偏听则暗》
  • 考研日语 - 高频核心 2200 词(八)
  • 【py】python实现矩阵的加、减、点乘、乘法
  • 多线程-初阶(1)
  • QT系统学习篇(1)
  • 算法笔记(九)——栈
  • 在springboot项目中实现一个定时任务执行的功能
  • 基于Springboot+Vue的小区停车场管理系统登录(含源码数据库)
  • wsl2 ubuntu 桥接以太网卡
  • git维护【.gitignore文件】
  • Microsoft 更新 Copilot AI,未來將能使用語音並看到你瀏覽的網頁
  • SpringCloud学习记录|day2
  • 手机实时提取SIM卡打电话的信令声音-(题外、插播一条广告)
  • Ubuntu安装Hadoop3.4
  • 书生大模型实战(从入门到进阶)L3-彩蛋岛-InternLM 1.8B 模型 Android 端侧部署实践
  • 常见的VPS或者独立服务器的控制面板推荐
  • 华为云LTS日志上报至观测云最佳实践