0%

PostgeSQL有serial字段的表插入记录时,要么不提供serial字段,要么为serial字段提供DEFAULT这个值。

有这么几种方法:

  • useGeneratedKeys

这是insert独有的属性,告诉Mybatis使用JDBC的getGeneratedKeys 方法去获取数据库内部产生的key。
如果自增键的名字不叫id,还需要设置一个属性keyProperty来告诉Mybaits获取回来的结果设置到那个字段上。
最好明确设置keyProperty属性

1
2
3
4
5
6
<insert id="insert" parameterType="org.xxx.xxx.entity.Building"
useGeneratedKeys="true" keyProperty="myid">

INSERT INTO ...

</insert>

使用Mybatis Generator生成mapper文件时,只要在table元素下添加子元素generatedKey即可,如下:

1
<generatedKey column="id" sqlStatement="JDBC"/>

column是自动生成的键,使用JDBC标准生成键方式。
最好将generatedKey子元素放到table元素的最后,否则可能会有错误提示。

  • selectKey

selectKey定义一个子查询,将查询的自增键的结果赋予insert参数的相应字段。selectKey有以下几个属性:

keyProperty - selectKey子查询的结果应该设置到传入参数的哪个字段上
resultType - 查询的结果类型。Mybaits其实可以自己查询出结果类型。
order - 插入语句执行之前还是之后执行selectKey子查询,只能取值BEFORE或AFTER
statementType - 语句类型。STATEMENT,PREPARED或CALLABLE

插入语句之后执行selectKey子查询

1
2
3
<selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">
SELECT currval('mytable_id_seq')
</selectKey>

插入语句之前执行selectKey子查询

1
2
3
<selectKey order="BEFORE" keyProperty="id" resultType="java.lang.Integer">
SELECT nextval('mytable_id_seq')
</selectKey>

PostgreSQL为serial字段生成的sequence名字为: 表名_列名_seq,但是这个序列并不能单独访问,否则会有提示:
ERROR: currval of sequence “mytable_id_seq” is not yet defined in this session

  • RETURNING子句

PostgreSQL的INSERT语句可以有一个RETURNING字句,返回刚插入记录的字段值。而且RETURNING的语法与SELECT是一样的,这个功能还是十分强大的,不过这是PostgreSQL独有的SQL标准之外的扩展特性。

1
2
3
<insert id="insert" parameterType="org.xxx.xxx.entity.Building" resultType="int">
INSERT INTO ... VALUES (...) RETURNING id
</insert>

useGeneratedKeys是最简单的,只要数据库支持就应该使用这个方法。

无论使用哪个方法,返回的自增键的值都应该从insert方法的参数对应的字段去取,而不是获取insert方法的返回值,insert方法总是返回INSERT INTO语句影响的行数,如果插入成功其值为1,如果插入失败其值为0

PostgreSQL重设serial类型主键从1开始。PostgreSQL为serial类型字段默认生成的序列sequence的名字为

_seq,可以用这个命令重设:ALTER SEQUENCE
_seq RESTART WITH 1;

JAVA boolean类型变量最好不要以is开头,否则可能会出现很多意想不到的问题。

使用mybatis:scan扫描mapper接口很方便
[xml]
<mybatis:scan base-package=”net.openwares.test.mapper” />
[/xml]

但要注意一点:
不要将非mapper接口放入指定的基本包中,因为默认情况下mybatis:scan会将包里的所有接口当作mapper来扫描,所以如果是其他接口就会出现错误。

可以在mybatis:scan元素的基本包里添加多个包,使用逗号或分号分割即可。

下面摘录自Mybatis文档

mybatis:scan/ supports filtering the mappers created by either specifying a marker interface or an annotation. The annotation property specifies an annotation to search for. The marker-interface attribute specifies a parent interface to search for. If both properties are specified, mappers are added for interfaces that match either criteria. By default, these two properties are null, so all interfaces in the given base package(s) will be loaded as mappers.

串接ls,grep和sed实现只列目录的命令,ls -F grep / sed “s/\///“,长模式列目录的话更简单ls -l grep /

当请求字典对象里面没有的key时,python会抛出异常KeyError。

如果不想抛出异常而是当没有对应的键时提供一个默认值,可以使用字典对象的get()方法:
[python]
val = adict.get(‘nonexist_key’, ‘default_value’)
print(val) #default_value
print(adict[‘nonexist_key’]) #KeyError: ‘nonexist_key’
[/python]
get()方法值提供默认值,不会为字典对象添加key

如果在访问字典没有对应key时想添加这个key,并设置默认值,可以使用字典对象的setdefault(key, val)方法,这个方法会返回已经存在key的value,只有当key不存在时才添加key,并返回默认值。

[python]
val = adict.setdefault(‘nonexsit_key’, ‘default_value’)
print(adict[‘nonexsit_key’]) # ‘default_value’
[/python]

===
[erq]

测试部署应用程序时,spring容器出现异常:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [xxx.xxx.service.UploadService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

明明UploadService是个POJO类都编译通过了,最后发现错误原因是service层的组件需要用@Service注解来修饰。那为啥DAO层的组件就没报错来!!!

注:知道为什么报错了,因为controller使用@Autowired(required=true)来引用UploadService,而UploadService没有使用注解修饰,从而不会被spring管理,故而出错。而DAO组件是Mybatis-Spring自动管理的,所以不会有问题。不加注解,spring是不会理会用户定义的POJO的。

好吧,以后DAO层组件也老老实实的加上@Repository注解,就算普通的POJO,如果需要spring容器来自动管理注入,也要用@Component注解修饰。

@Controller,@Service,@Repository,@Component都在包org.springframework.stereotype里。