@@ -41,16 +41,15 @@ private SqlColumn(Builder builder) {
4141 typeHandler = builder .typeHandler ;
4242 }
4343
44- @ SuppressWarnings ("unchecked" )
45- protected SqlColumn (SqlColumn <?> sqlColumn ) {
44+ protected SqlColumn (SqlColumn <T > sqlColumn ) {
4645 name = sqlColumn .name ;
4746 table = sqlColumn .table ;
4847 jdbcType = sqlColumn .jdbcType ;
4948 isDescending = sqlColumn .isDescending ;
5049 alias = sqlColumn .alias ;
5150 typeHandler = sqlColumn .typeHandler ;
5251 renderingStrategy = sqlColumn .renderingStrategy ;
53- parameterTypeConverter = ( ParameterTypeConverter < T , ?>) sqlColumn .parameterTypeConverter ;
52+ parameterTypeConverter = sqlColumn .parameterTypeConverter ;
5453 }
5554
5655 public String name () {
@@ -119,25 +118,39 @@ public Optional<RenderingStrategy> renderingStrategy() {
119118
120119 @ NotNull
121120 public <S > SqlColumn <S > withTypeHandler (String typeHandler ) {
122- SqlColumn <S > column = new SqlColumn <>( this );
121+ SqlColumn <S > column = copy ( );
123122 column .typeHandler = typeHandler ;
124123 return column ;
125124 }
126125
127126 @ NotNull
128127 public <S > SqlColumn <S > withRenderingStrategy (RenderingStrategy renderingStrategy ) {
129- SqlColumn <S > column = new SqlColumn <>( this );
128+ SqlColumn <S > column = copy ( );
130129 column .renderingStrategy = renderingStrategy ;
131130 return column ;
132131 }
133132
134133 @ NotNull
135134 public <S > SqlColumn <S > withParameterTypeConverter (ParameterTypeConverter <S , ?> parameterTypeConverter ) {
136- SqlColumn <S > column = new SqlColumn <>( this );
135+ SqlColumn <S > column = copy ( );
137136 column .parameterTypeConverter = parameterTypeConverter ;
138137 return column ;
139138 }
140139
140+ /**
141+ * This method helps us tell a bit of fiction to the Java compiler. Java, for better or worse,
142+ * does not carry generic type information through chained methods. We want to enable method
143+ * chaining in the "with" methods. With this bit of fiction, we force the compiler to delay type
144+ * inference to the last method in the chain.
145+ *
146+ * @param <S> the type. Will be the same as T for this usage.
147+ * @return a new SqlColumn of type S (S is the same as T)
148+ */
149+ @ SuppressWarnings ("unchecked" )
150+ private <S > SqlColumn <S > copy () {
151+ return new SqlColumn <>((SqlColumn <S >) this );
152+ }
153+
141154 private String applyTableAlias (String tableAlias ) {
142155 return tableAlias + "." + name (); //$NON-NLS-1$
143156 }
0 commit comments