一、创建一个简单的查询数据库的服务端Demo
以:
1)数据库为PostgreSQL数据库
2)数据库创建UserTable表,包含name、password、address、sexxy属性,表中包含三条数据
“zhangsan”、“123456”、“shenzhen”、“male”
“lisi”、“abcdef”、“shanghai”、“male”
“lili”、“abc456”、“beijing”、“famale”
3)通过样例项目,在web呈现数据库查询结果
http://localhost:8080/user/hello 打印hello world。
http://localhost:8080/user/findUser/用户名 打印从数据库中查询select * from UserTable where name='用户名'的内容。
http://localhost:8080/user/getUser/用户名/密码 打印从数据库中查询select * from UserTable where name='用户名' and password=‘密码’的内容。
1、PostgreSQL数据库创建表,并插入数据
启动PostgreSQL的SQL Shell,默认用户名postgres,密码为123456,默认端口:5432
创建表:
CREATE TABLE UserTable(name Char(15) primary KEY NOT NULL,password Char(8) NOT NULL,address char(100),sexxy int);
表中插入数据:
INSERT INTO UserTable VALUES('zhangsan','123456','shenzhen',1);
INSERT INTO UserTable VALUES('lisi','abcdef','shanghai',1);
INSERT INTO UserTable VALUES('lili','abc456','beijing',0);
2、创建Java Spring boot项目。
打开IDEA环境,创建新的工程。项目类型选择“Spring Initializr”,选择SDK。
填写“Group”、“Artifact”,Type选择“Maven Project”。
选择项目依赖:“Developer Tools“-》“Spring Boot DevTools”,“Web”-》“Spring Web”,“SQL”-》“JDBC API”,“SQL”-》“Spring Data JDBC”,“SQL”-》“MyBatis Framwork”,“SQL”-》“PostgreSQL Driver”
项目创建完毕后,目录结构如下:
pom.xml文件中关键内容如下:
3.编写Java源码
源码目录结构如下:
DemoUser.java,定义了数据库对应表对应的结构,内容如下:
package com.example.postgresqlexample.entity;
import java.lang.String;
public class DemoUser {
private String name;
private String password;
private String address;
private Integer sexxy;
public void User(String name, String password, String address, Integer sexxy) {
this.name = name;
this.password = password;
this.address = address;
this.sexxy = sexxy;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getSexxy() {
return sexxy;
}
public void setSexxy(Integer sexxy) {
this.sexxy = sexxy;
}
@Override
public String toString(){
String strSexxy;
if(this.sexxy == 1) {
strSexxy = "male";
}
else{
strSexxy = "female";
}
return "User(name:" + this.name + " password:" + this.password + " address:" + this.address + " sexxy:" + strSexxy;
}
}
UserMapper.java文件定义了和PostgreSQL数据库交互的API接口,内容如下:
package com.example.postgresqlexample.dao;
import com.example.postgresqlexample.entity.DemoUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.lang.String;
@Mapper
public interface UserMapper {
//@Select({"select * from UserTable where name=#{name}"})
DemoUser findByName(String name);
@Select({"select * from UserTable where name=#{name} and password=#{password}"})
DemoUser getByNameAndPsword(String name, String password);//根据用户名和邮箱进行查询
}
DemeService.java内容定义如下,供Controller调用:
package com.example.postgresqlexample.services;
import com.example.postgresqlexample.dao.UserMapper;
import com.example.postgresqlexample.entity.DemoUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class DemoService {
@Resource
private UserMapper userMapper;
public DemoUser findByName(String name) {
DemoUser u = userMapper.findByName(name);
return u;
}
public DemoUser findByNameAndPsword(String name, String password){
DemoUser u = userMapper.getByNameAndPsword(name, password);
return u;
}
}
DemoController.java定义Web访问的URI和DemoService.java中结构的对应关系:
package com.example.postgresqlexample.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.postgresqlexample.services.DemoService;
@RestController
@RequestMapping("/user")
public class DemoController {
@Autowired
DemoService demoService;
@RequestMapping("/hello")
public String hello() {
return "Hello User!";
}
@RequestMapping("/getUser/{name}/{password}")
public String getUserByNameAndPW(@PathVariable String name, @PathVariable String password) {
return demoService.findByNameAndPsword(name, password).toString();
}
@RequestMapping("/findUser/{name}")
public String findUserByName(@PathVariable String name) {
return demoService.findByName(name).toString();
}
}
PostgresqlexampleApplication.java是Springboot框架自动生成,为程序入口,保持自动生成的内容即可。
4. 配置和PostgreSQL数据的接口
包含两个部分:
(1)在resource目录下场景Mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.postgresqlexample.dao.UserMapper">
<resultMap id="UserMap" type="com.example.postgresqlexample.entity.DemoUser">
<id property="name" column="name"/>
<result property="password" column="password"/>
<result property="address" column="address"/>
<result property="sexxy" column="sexxy"/>
</resultMap>
<select id="findByName" resultMap="UserMap">
select * from UserTable where name=#{name}
</select>
</mapper>
注1:
A、<resultMap>标签定义了PostgreSQL查询结果对应的Java中的结构体,定义在type=后面。(实际测试:这个demo中,<resulttMap>标签内的<id>、<result>定义可以不要,不影响demo效果。)
B、这里的<select>标签配置了dao/UserMapper.java中接口和SQL语句之间的关系。id为UserMapper.java中接口名;#{name}中内容要和<resultMap>标签中type定义的dao/UserMapper.java中类函数findByName(String name)参数名称一致(实际测试:如果select语句只有一个参数,#{name}内容随便写,比如#{xxxx},依然能查询成功。但是如果select语句包含多个参数,如:where name=#{name} and password=#{password},则#{}内的内容必须与dao/UserMapper.java中类函数参数名称一致)。
注2:
在UserMapper.java中定义接口,在UserMapper.xml中定义接口对应的SQL一句是一种方式。另外一种方式是直接在UserMapper.java中定义接口对应的SQL语句,详见UserMapper.java中getByNameAndPsword接口。
(2)配置和PostgreSQL对接
方式一:application.properties配置
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=123456
spring.datasource.driverClassName=org.postgresql.Driver
mybatis.typeAliasesPackage=com.example.postgresqlexample.entity
mybatis.mapperLocations=classpath:mapper/*.xml
方式二:采用applicaion.yml配置
spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
mybatis:
type-aliases-package: com.example.postgresqlexample.entity
mapper-locations: classpath:mapper/*.xml
5. 编译、测试
编译完毕后,IDEA执行run。
在ie浏览器分别输入:
http://localhost:8080/user/hello
http://localhost:8080/user/findUser/zhangsan
http://localhost:8080/user/getUser/zhangsan/123456
查看效果。
6.Demo中遇到的问题参考:
(1)运行后,在ie浏览器访问findUser,报类似如下错误:Invalid bound statement (not found): com.example.postgresqlexample.dao.UserMapper.findByName] with root cause。 最终原因:application.properties或application.yml中mapper-locations如果没有配置,会导致最终结果中UserMapper.xml无效,找不到findByName函数对应的SQL定义。
(2)运行后,在ie浏览器访问findUser、getUser都报错:Error querying database. Cause: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
最终原因:DemoUser构造函数入参个数错误(本来只有三个对象,做其他改造增加了2个入参未删除-共5个入参),导致后续从PostgreSQL查到出结果后,创建DemoUser对象失败。
(3)查询数据库错误。最终原因:Usermapper.xml中的如下type路径错误。<resultMap id="UserMap" type="com.example.postgresqlexample.entity.DemoUser">